OPNsense Forum

English Forums => Tutorials and FAQs => Topic started by: punkt2folger15 on February 16, 2025, 07:00:14 PM

Title: [HowTo] Keycloak in jails under OPNsense
Post by: punkt2folger15 on February 16, 2025, 07:00:14 PM
This is a tutorial to setup [Keycloak](https://www.keycloak.org/) as a jail inside OPNsense, as it is not available as a plugin at the time of writing. I leave it to you to decide for yourself whether to have such services in jails inside OPNsense or not.

Thanks to the following posts for inspiration and providing valuable information:
[Jails documentation](https://docs.freebsd.org/en/books/handbook/jails/)
[Jails under OPNsense](https://forum.opnsense.org/index.php?topic=26975.0)
[FreeBSD jails](https://vermaden.wordpress.com/2023/06/28/freebsd-jails-containers/)
[FreeBSD Keycloak](https://vermaden.wordpress.com/2024/03/10/keycloak-on-freebsd/)

For my future self and others, in this tutorial, I quickly show how to setup vnet jail and then run Keycloak inside jail. You can adapt it based on your requirements. I have tested it with OPNsense 24.1, 24.7 and 25.1, also FreeBSD 14.1 and 14.2 release.

This tutorial only covers the basic setup and so for further adaptation refer to documentation of jails and Keycloak accordingly. Please proceed at your own risks.


1. Basic Jail setup under OPNsense

  • To setup a jail, we first create a zpool on the disk. Its upto you to use an existing disk or a separate disk. Here, I am using a separate disk (/dev/da1)
  • Then, we create three zfs datasets on the zpool: jail base (to hold our base jail contents), jail template (in case we need a jail template to use later) and individual jail folders
  • Below is the list of commands to create zpool and datasets. Adapt according to your needs

zpool create -f jailstore /dev/da1
zfs create jailstore/jailstore
zfs create jailstore/jailstore/jailbase
zfs create jailstore/jailstore/jailtemplate
zfs create jailstore/jailstore/keycloakvnet
fetch -o /jailstore/jailstore/jailbase/14.2-RELEASE-base.txz http://ftp.freebsd.org/pub/FreeBSD/releases/amd64/14.2-RELEASE/base.txz
tar -xf /jailstore/jailstore/jailbase/14.2-RELEASE-base.txz -C /jailstore/jailstore/keycloakvnet --unlink

  • In OPNsense, create an empty bridge or add an existing interface (whatever, depends on your setup) and then assign and activate the interface
  • To setup empty bridge, follow the steps here: https://docs.opnsense.org/manual/other-interfaces.html#bridge
  • Then assign the interface with a static ip (for example: 10.10.10.1/24 or whatever depends on your setup)
  • Optionally, you can also setup dhcp
  • Enable jails in OPNsense, by placing these lines in /etc/rc.conf file:

jail_enable="YES"
jail_parallel_start="YES"
jail_list="keycloakvnet"

  • Create keycloak jails configuration by creating a file /etc/jail.conf.d/keycloakvnet
keycloakvnet {

  # Variables for NETWORKS/INTERFACES
  $ida = "10";  #epaira that sits outside jails and connects to the bridge interface
  $idb = "11";  #epairb that sits inside jails and connects to epaira outside
  $ipa = "10.10.10.${ida}/24";
  $ipb = "10.10.10.${idb}/24";
  $gw = "10.10.10.1";
  $br = "bridge0";
  $if = "epair${ida}";

  # STARTUP/LOGGING
  exec.start = "/bin/sh /etc/rc";
  exec.stop  = "/bin/sh /etc/rc.shutdown";
  exec.consolelog = "/var/log/jail_console_${name}.log";

  # PERMISSIONS
  allow.raw_sockets;
  exec.clean;
  # helps with mounting filesystems
  mount.devfs;
  exec.prepare += "service devfs start";
  # helps with postgres setup memory allocation
  sysvmsg = new;
  sysvsem = new;
  sysvshm = new;

  # PATH/HOSTNAME
  path = "/jailstore/jailstore/${name}";
  host.hostname = "${name}";
  # host.hostname = "keycloakvnet.localdomain";

  # VNET/VIMAGE
  vnet;
  vnet.interface = "${if}b";

  # Network settings
  exec.prepare += "ifconfig ${if} create";
  exec.prepare += "ifconfig ${if}a descr jail:${name}";
  exec.prepare += "ifconfig ${br} addm ${if}a up";
  exec.prepare += "ifconfig ${if}a inet ${ipa} up";

  exec.start += "ifconfig ${if}b inet ${ipb} up";
  exec.start += "route add default ${gw}";
  exec.prestop += "ifconfig ${if}b -vnet $name";
  exec.release += "ifconfig ${if}a destroy";

}

  • Some useful commands related to jails operations
# Start the jail
service jail start keycloakvnet
# to stop the jail
service jail stop keycloakvnet
# to login as root user
jexec keycloakvnet login -f root
# to login as someuser
jexec keycloakvnet login -f someuser
# to list jails
jls
# to get inside jail
jexec keycloakvnet /bin/sh
# to login using bash (works only if bash is configured inside jail)
jexec keycloakvnet usr/local/bin/sh

  • Now, start the jail and get inside the jail using the commands listed above
  • you should be inside jail now and so test the commands below inside the jail

# all commands below are run inside jail unless specified
# to look at the interfaces
netstat -Win -f inet
# to enable dns, use your nameserver of choice
echo nameserver 9.9.9.9 > /etc/resolv.conf
# to test whether dns works.
drill freebsd.org | grep '^[^;]'
# Note: If this doesn't work, then go to your OPNsense firewall for the vnet jail interface and set rules to allow dns and outside access. make sure to place necessary rules according to your setup and test it again

  • allow root login via ssh - adapt according to needs and your setup
cat << EOF >> /etc/ssh/sshd_config
PermitRootLogin yes
UseDNS no
EOF

  • enable and start sshd service
service sshd enable
service sshd start
# to see if ssh port is listed
sockstat -l4

  • set root password
passwd
  • set hushlogin to avoid displaying motd while logging in through ssh
touch ~/.hushlogin
  • Setup hostname by editing /etc/rc.conf
  • This is very important as Keycloak has a strict hostname checks for production use and its always good to have proper hostname
hostname="keycloakvnet.localdomain"
  • add entry to /etc/hosts
echo 10.10.10.11 keycloakvnet.localdomain keycloak >> /etc/hosts

  • Make sure package repo is available
mkdir -p /usr/local/etc/pkg/repos
sed -e s/quarterly/latest/g /etc/pkg/FreeBSD.conf > /usr/local/etc/pkg/repos/FreeBSD.conf

  • Restart the services which were modified
service netif restart
service routing restart
service hostname restart

  • Optional: Just to check if all working, simply stop and jail and start the jail and login as root

  • Continue to configure jail and Keycloak
# update pkg, if asked answer yes
pkg update

  • install basic packages, some are optional, adapt according to your needs
pkg install -y wget curl nano bash bash-completion tree git sudo

  • add a non-root user and enable wheel sudo access, answer the questions according to needs
adduser
  • sudo access-> open and uncomment the line %Wheel....
visudo


2. Installation and configuratio of keycloak
Part 1: Database configuration

  • Keycloak requires a database. Here, i show postgresql.
  • Note: I am showing postgresql and keycloak both residing on the same jail. If you prefer you can create two jails, one for postgresql and another for Keycloak. If so, make sure to adjust the settings according to your setup
pkg install -y keycloak postgresql17-server postgresql17-client
service postgresql enable
service postgresql initdb
service postgresql start
sockstat -l4

  • configure postgresql by login into postgresql and entering commands
su - postgres -c psql
# If you are inside postgresql, the you should see the prompt like this:
postgres=#

# Note: If you prefer to have a separate user, create and use it. Here, the default postgres user is used
# setup password for postgres user. Make sure to use a secure and postgres complainant password
\password postgres

# create a databse for Keycloak to use
CREATE DATABASE keycloak with encoding 'UTF8';
# If database is created, then your should see this as output: CREATE DATABASE

# grant all acceess to keycloak database to postgres user
GRANT ALL ON DATABASE keycloak TO postgres;
# If database is created, then your should see this as output: GRANT

# exit postgresql prompt and return to your jail prompt
\q

Part 2: Keycloak configuration

  • go to keycloak conf folder
cd /usr/local/share/java/keycloak/conf

  • Generate certificates or use your own from OPNsense trust store by importing it here.
  • For more info refer here: https://www.keycloak.org/server/enabletls
openssl req -newkey rsa:2048 -nodes -keyout keycloak-server.key.pem -x509 -days 3650 -out keycloak-server.crt.pem

  • change the permission and ownership of the certificate files
chmod 600 keycloak-server.crt.pem keycloak-server.key.pem
chown keycloak:keycloak keycloak-server.crt.pem keycloak-server.key.pem

  • Create keycloak.conf or modify the keycloak.conf sample file.
  • For more info refer here: https://www.keycloak.org/guides

vi /usr/local/share/java/keycloak/conf/keycloak.conf
db=postgres
# If you have opted for a different user, then use that
db-username=postgres
# This is not a good way, as password is visible, but for now usng this as an example. for secure option refer Keycloak guides: https://www.keycloak.org/server/vault
db-password=password
# If you have opted to run the database separately, then replace localhost:5432 to your database
db-url=jdbc:postgresql://localhost:5432/keycloak
hostname-strict-https=true
hostname-url=https://keycloakvnet.localdomain:8443/
hostname-admin-url=https://keycloakvnet.localdomain:8443/
hostname=keycloakvnet.localdomain
# path to the certificate files
https-certificate-file=/usr/local/share/java/keycloak/conf/keycloak-server.crt.pem
https-certificate-key-file=/usr/local/share/java/keycloak/conf/keycloak-server.key.pem
proxy=edge

  • make sure quarkus properties file is enabled for recovery and set permissions

echo quarkus.transaction-manager.enable-recovery=true > /usr/local/share/java/keycloak/conf/quarkus.properties
chown keycloak:keycloak /usr/local/share/java/keycloak/conf/quarkus.properties

  • Enable Keycloak service
service keycloak enable

  • Before Keycloak can be started, the configuration needs to be loaded to the Keycloak component. So, build keycloak config
  • Note: If you make any changes to keycloak config then this command needs to be run each time
service keycloak build

  • check the config and make sure everything is set as per your setup
/usr/local/share/java/keycloak/bin/kc.sh show-config

  • Bootstrap temporary admin user; just give some temporary name and password as this user will be replaced with a proper admin user after first login
/usr/local/share/java/keycloak/bin/kc.sh bootstrap-admin user

  • Start Keycloak service
service keycloak start

  • To check log
tail -f /var/log/keycloak/keycloak.out

  • If all is fine, then you can login to the keycloak dashboard by going to https://keycloakvnet.localdomain:8443
  • Make sure you have proper dns setup to resolve this domain
  • Login using the temporary admin user and password. After login go to users and create a proper admin with roles.
  • For more info and further configuration, refer keycloak guides
  • From here on, you can configure Keycloak and use it according to your needs


  • To stop keycloak
service keycloak stop

  • If its not stopping kill it by entering pid of keycloak. replace PID with process id of keycloak
kill -KILL PID