Running Oracle Database 23ai Free on Raspberry Pi 5 via Podman

Recently, I blogged about how I’ve released ARM-based Oracle Database Free container images on gvenzl/oracle-free and how that enables folks to run these images on ARM-native machines. Well, Raspberry Pis are ARM-native machines, and you can indeed run Oracle Database Free also on a Raspberry Pi 5; here is how.

Raspberry Pi 5 setup

All tests are one on a Raspberry Pi 5 with:

  • 8 GB of RAM
  • 128 GB SanDisk Extreme Plus SD card
  • Raspberry Pi OS (64-bit) Debian Bookworm

Unfortunately, things are not quite as easy as booting up Raspberry Pi OS and off you go. Neither Podman, Docker, or Rancher are installed by default, the kernel itself runs with a 16kb memory frame or page size, while most Linux kernels run with 4kb, including Oracle Linux, for which the Oracle Database has been compiled, and cgoups memory is not enabled. Luckily, all of these are easy fixes, though.

Changing the Kernel memory page size

If you were to just run an Oracle Database Free container with the 16kb page size default, you would encounter the following error:

gvenzl@gvenzl-rbp-5:~ $ podman run --name test -e ORACLE_PASSWORD=foo docker.io/gvenzl/oracle-free:slim
Trying to pull docker.io/gvenzl/oracle-free:slim...
Getting image source signatures
Copying blob eebeeaf0d8a1 done
Copying blob 93a4ffe4148f done
Copying blob 346f330e5796 done
Copying blob ad5284a72156 done
Copying blob 2a686015a85f done
Copying blob 6e2355abcef4 done
Copying config d342af205c done
Writing manifest to image destination
Storing signatures
CONTAINER: starting up...
sqlplus: error while loading shared libraries: libclntsh.so.23.1: ELF load command alignment not page-aligned

That’s not a very user-friendly error message, is it? But if you google for the error message ELF load command alignment not page-align, you will quickly find the following Raspberry Pi OS topic: https://forums.raspberrypi.com/viewtopic.php?t=361390, stating that the kernel runs with 16kb page size. To verify the current page size, you can run the getconf PAGESIZE command (case-sensitive) in the shell:

gvenzl@gvenzl-rbp-5:~ $ getconf PAGESIZE
16384

It indeed shows that the kernel is running with a 16kb page size. Fortunately, Raspberry Pi OS still comes with a 4kb page size kernel that you can use. All you have to do is to add the additional line kernel=kernel8.img to the /boot/firmware/config.txt file and reboot the system. This is done quickest via these two commands (note, the new line in the echo command is intentional and note that you can spare yourself this reboot and proceed to Enabling cgroups memory):

sudo sh -c "echo '
kernel=kernel8.img' >> /boot/firmware/config.txt"

sudo reboot

Once rebooted, verify the page size one more time with getconf PAGESIZE:

gvenzl@gvenzl-rbp-5:~ $ getconf PAGESIZE
4096

Enabling cgroups memory

To see what cgroups functionality is and isn’t enabled, look into the /proc/cgroups file. The number at the very right indicates whether the functionality is enabled (=1) or disabled (=0):

gvenzl@gvenzl-rbp-5:~ $ cat /proc/cgroups
#subsys_name    hierarchy    num_cgroups    enabled
cpuset                  0             68          1
cpu                     0             68          1
cpuacct                 0             68          1
blkio                   0             68          1
memory                  0             68          0
devices                 0             68          1
freezer                 0             68          1
net_cls                 0             68          1
perf_event              0             68          1
net_prio                0             68          1
pids                    0             68          1

A quick glance at the contents of that file shows that the row for the subsystem memory has a 0 for the enabled column, and hence, that subsystem is disabled. To enable cgroups memory, the key/value pair "cgroup_enable=memory" has to be added to the kernel boot parameters in the /boot/firmware/cmdline.txt file, and the system rebooted. This is done quickest via these two commands (note the " " (space) in front of " cgroup_enable=memory":

sudo sh -c 'echo " cgroup_enable=memory" >> /boot/firmware/cmdline.txt'

sudo reboot

Once the system is back up again, verify that the cgroups memory subsystem is enabled by checking /proc/cgroups once more:

gvenzl@gvenzl-rbp-5:~ $ cat /proc/cgroups
#subsys_name    hierarchy    num_cgroups    enabled
cpuset                  0            108          1
cpu                     0            108          1
cpuacct                 0            108          1
blkio                   0            108          1
memory                  0            108          1
devices                 0            108          1
freezer                 0            108          1
net_cls                 0            108          1
perf_event              0            108          1
net_prio                0            108          1
pids                    0            108          1

Installing Podman

Now that the OS is ready, all that’s left to do is install a container runtime like Podman. The Podman installation is straightforward, just run sudo apt-get install podman -y:

sudo apt-get install podman -y
gvenzl@gvenzl-rbp-5:~ $ sudo apt-get install podman -y
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following additional packages will be installed:
  aardvark-dns buildah catatonit conmon containernetworking-plugins crun fuse-overlayfs golang-github-containers-common
  golang-github-containers-image libslirp0 libsubid4 netavark slirp4netns uidmap
Suggested packages:
  containers-storage docker-compose
The following NEW packages will be installed:
  aardvark-dns buildah catatonit conmon containernetworking-plugins crun fuse-overlayfs golang-github-containers-common
  golang-github-containers-image libslirp0 libsubid4 netavark podman slirp4netns uidmap
0 upgraded, 15 newly installed, 0 to remove and 0 not upgraded.
Need to get 0 B/23.2 MB of archives.
After this operation, 110 MB of additional disk space will be used.
Selecting previously unselected package netavark.
(Reading database ... 150524 files and directories currently installed.)
Preparing to unpack .../00-netavark_1.4.0-3_arm64.deb ...
Unpacking netavark (1.4.0-3) ...
Selecting previously unselected package aardvark-dns.
Preparing to unpack .../01-aardvark-dns_1.4.0-3_arm64.deb ...
Unpacking aardvark-dns (1.4.0-3) ...
Selecting previously unselected package libsubid4:arm64.
Preparing to unpack .../02-libsubid4_1%3a4.13+dfsg1-1+b1_arm64.deb ...
Unpacking libsubid4:arm64 (1:4.13+dfsg1-1+b1) ...
Selecting previously unselected package uidmap.
Preparing to unpack .../03-uidmap_1%3a4.13+dfsg1-1+b1_arm64.deb ...
Unpacking uidmap (1:4.13+dfsg1-1+b1) ...
Selecting previously unselected package containernetworking-plugins.
Preparing to unpack .../04-containernetworking-plugins_1.1.1+ds1-3+b5_arm64.deb ...
Unpacking containernetworking-plugins (1.1.1+ds1-3+b5) ...
Selecting previously unselected package golang-github-containers-image.
Preparing to unpack .../05-golang-github-containers-image_5.23.1-4_all.deb ...
Unpacking golang-github-containers-image (5.23.1-4) ...
Selecting previously unselected package golang-github-containers-common.
Preparing to unpack .../06-golang-github-containers-common_0.50.1+ds1-4_all.deb ...
Unpacking golang-github-containers-common (0.50.1+ds1-4) ...
Selecting previously unselected package buildah.
Preparing to unpack .../07-buildah_1.28.2+ds1-3+b1_arm64.deb ...
Unpacking buildah (1.28.2+ds1-3+b1) ...
Selecting previously unselected package catatonit.
Preparing to unpack .../08-catatonit_0.1.7-1+b1_arm64.deb ...
Unpacking catatonit (0.1.7-1+b1) ...
Selecting previously unselected package conmon.
Preparing to unpack .../09-conmon_2.1.6+ds1-1_arm64.deb ...
Unpacking conmon (2.1.6+ds1-1) ...
Selecting previously unselected package crun.
Preparing to unpack .../10-crun_1.8.1-1+deb12u1_arm64.deb ...
Unpacking crun (1.8.1-1+deb12u1) ...
Selecting previously unselected package fuse-overlayfs.
Preparing to unpack .../11-fuse-overlayfs_1.10-1_arm64.deb ...
Unpacking fuse-overlayfs (1.10-1) ...
Selecting previously unselected package libslirp0:arm64.
Preparing to unpack .../12-libslirp0_4.7.0-1_arm64.deb ...
Unpacking libslirp0:arm64 (4.7.0-1) ...
Selecting previously unselected package podman.
Preparing to unpack .../13-podman_4.3.1+ds1-8+deb12u1_arm64.deb ...
Unpacking podman (4.3.1+ds1-8+deb12u1) ...
Selecting previously unselected package slirp4netns.
Preparing to unpack .../14-slirp4netns_1.2.0-1_arm64.deb ...
Unpacking slirp4netns (1.2.0-1) ...
Setting up crun (1.8.1-1+deb12u1) ...
Setting up libsubid4:arm64 (1:4.13+dfsg1-1+b1) ...
Setting up golang-github-containers-image (5.23.1-4) ...
Setting up conmon (2.1.6+ds1-1) ...
Setting up containernetworking-plugins (1.1.1+ds1-3+b5) ...
Setting up catatonit (0.1.7-1+b1) ...
Setting up netavark (1.4.0-3) ...
Setting up aardvark-dns (1.4.0-3) ...
Setting up libslirp0:arm64 (4.7.0-1) ...
Setting up fuse-overlayfs (1.10-1) ...
Setting up golang-github-containers-common (0.50.1+ds1-4) ...
Setting up slirp4netns (1.2.0-1) ...
Setting up uidmap (1:4.13+dfsg1-1+b1) ...
Setting up podman (4.3.1+ds1-8+deb12u1) ...
Setting up buildah (1.28.2+ds1-3+b1) ...
Processing triggers for man-db (2.11.2-2) ...
Processing triggers for libc-bin (2.36-9+rpt2+deb12u8) ...
gvenzl@gvenzl-rbp-5:~ $

Optional: add docker.io and/or ghcr.io to your registries

By default, Raspberry Pi OS won’t have predefined unqualified search container registries in /etc/containers/registries.conf. That means that if you wanted to pull an image, you would always have to fully qualify <server>/<group>/<repo>, i.e. docker.io/gvenzl/oracle-free. If you want to avoid a couple of extra keystrokes, open the /etc/containers/registries.conf file with your favorite editor and add the following line to it: unqualified-search-registries = ["docker.io", "ghcr.io"]

The easiest way to do this is via the following command (note the new line in the echo command is intentional):

sudo sh -c 'echo "
unqualified-search-registries = [\"docker.io\", \"ghcr.io\"]" >> /etc/containers/registries.conf'

Run Oracle Database 23ai Free

Once you have gone through all the setup steps, you can now run your Oracle Database Free via the usual podman|docker run ..., for example: podman run --name test -d -e ORACLE_PASSWORD=LetsTest1 docker.io/gvenzl/oracle-free:slim

gvenzl@gvenzl-rbp-5:~ $ podman run --name test -e ORACLE_PASSWORD=LetsTest1 docker.io/gvenzl/oracle-free:slim
Trying to pull docker.io/gvenzl/oracle-free:slim...
Getting image source signatures
Copying blob ad5284a72156 done
Copying blob 346f330e5796 done
Copying blob 93a4ffe4148f done
Copying blob 2a686015a85f done
Copying blob 6e2355abcef4 done
Copying blob eebeeaf0d8a1 done
Copying config d342af205c done
Writing manifest to image destination
Storing signatures
CONTAINER: starting up...
CONTAINER: first database startup, initializing...
CONTAINER: uncompressing database data files, please wait...
CONTAINER: done uncompressing database data files, duration: 53 seconds.
CONTAINER: starting up Oracle Database...

LSNRCTL for Linux: Version 23.0.0.0.0 - Production on 21-SEP-2024 19:17:18

Copyright (c) 1991, 2024, Oracle.  All rights reserved.

Starting /opt/oracle/product/23ai/dbhomeFree/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 23.0.0.0.0 - Production
System parameter file is /opt/oracle/product/23ai/dbhomeFree/network/admin/listener.ora
Log messages written to /opt/oracle/diag/tnslsnr/2913e0478639/listener/alert/log.xml
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_FREE)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))

Connecting to (DESCRIPTION=(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC_FOR_FREE)))
STATUS of the LISTENER
------------------------
Alias                     LISTENER
Version                   TNSLSNR for Linux: Version 23.0.0.0.0 - Production
Start Date                21-SEP-2024 19:17:19
Uptime                    0 days 0 hr. 0 min. 1 sec
Trace Level               off
Security                  ON: Local OS Authentication
SNMP                      OFF
Default Service           FREE
Listener Parameter File   /opt/oracle/product/23ai/dbhomeFree/network/admin/listener.ora
Listener Log File         /opt/oracle/diag/tnslsnr/2913e0478639/listener/alert/log.xml
Listening Endpoints Summary...
  (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC_FOR_FREE)))
  (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=0.0.0.0)(PORT=1521)))
The listener supports no services
The command completed successfully
ORACLE instance started.

Total System Global Area 1603726640 bytes
Fixed Size		    5360944 bytes
Variable Size		  805306368 bytes
Database Buffers	  788529152 bytes
Redo Buffers		    4530176 bytes
Database mounted.
Database opened.

CONTAINER: Resetting SYS and SYSTEM passwords.

User altered.

User altered.

#########################
DATABASE IS READY TO USE!
#########################

Lastly, a word of caution. Yes, you can run Oracle Database Free on a Raspberry Pi 5, but the SD card and I/O bandwidth to it are rather limited compared to modern laptops or servers. Note how the uncompress operation of the data files alone took 53 seconds, while it took about 5 seconds on my laptop. So be prepared to have some longer wait times or perhaps explore some other I/O alternatives if you assume a lot of I/O workload to be done.

16 thoughts on “Running Oracle Database 23ai Free on Raspberry Pi 5 via Podman”

  1. Vijiaselvam Nayagam

    thank you for a great writeup

    am in installing OraDB on windows server 2022 using hyper-v

    I want to try on Pi5 as I have one unit lying around.

    thanks

      1. Vijiaselvam Nayagam

        Hi Gerald

        I have tried twice but it always stops at this …

        Trying to pull docker.io/gvenzl/oracle-free:slim…
        Getting image source signatures
        Copying blob c8d326c895da done
        Copying blob a6cb3aa2f765 done
        Copying blob b3066d703646 done
        Copying blob e47df9f05a8a done
        Copying blob 8005aee7dad7 done
        Copying blob 737938346901 done
        Copying config c623a74f32 done
        Writing manifest to image destination
        Storing signatures
        66a7b9cce43db27898962d47c308317c2f1fea4ff953a902f17631f00865a8ba

        ….
        CONTAINER: starting up...
        …this does not happen

        what could be the issue…

        i use Oracle21c for work running off WinServer2022
        hyper-v – i am v familiar
        Podman & Docker – i am too new
        Linux – I am not familiar too much

        Thank You

        1. Hi Vijiaselvam,

          On which environment are you trying to start the database? Can you provide more details about the host, OS, container runtime version?

          Thanks,

          1. Vijiaselvam Nayagam

            Hi Gerald
            am sorry to trouble you
            I installed on a Pi 5 with 8gb running Raspberry Pi OS (Desktop)

            I think I need to learn more bout Podman and I will definitely get it figured.
            If I can manage Hypervisor since dozens years ago, I think I can and will pick this Container stuff up.
            Give me some time to learn and I will get back to you.
            Thanks for your article which got me to venture into Containers

            some background
            For work-related testing, we use a Windows Server 2022 with Oracle 21c running in Hyper-V, we share among team members for testing and trouble shooting.

            I wanted to try Containers on my Pi-5 to learn and see if I could use Containers in replacing my Hyper-V which is quite large (300+ GB)

            Thanks Gerald
            have a great day ahead

          2. Hi Vijiaselvam,

            It’s no trouble, don’t worry. 🙂

            Ok, thank you! Raspberry Pis are rather slow when it comes to IO, that’s mostly because they use SD cards and SD cards are not made for high speed write or even random writes. For example, the SanDisk 256GB Extreme PRO (SanDisk 256GB Extreme PRO SDXC UHS-I Memory Card – C10, U3, V30, 4K UHD, SD Card – SDSDXXD-256G-GN4IN, Dark gray/Black) that I’m using, is rated with only 200MB/s and in the fine print it states only 140MB/s for writes in optimal conditions (Shot speeds up to 140MB/s (Write speed up to 140MB/s. Based on internal testing; performance may be lower depending upon host device, interface, usage conditions and other factors. 1MB=1,000,000 bytes. X = 150KB/sec.))

            When the container starts, it first unzips the database files, which is about 3 GB for the slim image. That is a 21.64 seconds at the best maximum theoretical write speed of 140MB/s. So basically, this means starting a larger sized container on a Raspberry Pi 5 takes much longer than on, e.g. a laptop with an SSD. For example, my old 2020 Mac Book has an SSD that is rated with 2,669 MBytes/Sec write speed. That is 19x faster than the SD card in my Raspberry Pi 5.

            So even for me, spinning up an Oracle Database container takes quite a while on the Raspberry Pi 5. I just timed it and it comes down to 1 minute and 20 seconds without having to download the image first.

            There is also an element regard the CPU. The Raspberry Pi 5 really needs active cooling, otherwise the CPU gets just too hot and throttles itself, see https://www.raspberrypi.com/news/heating-and-cooling-raspberry-pi-5/

            Hope this helps!

          3. Vijiaselvam Nayagam

            hi Gerald,

            thanks for the heads up, I totally agree and I will halt the Pi-5 dance.

            Maybe it’s better to fire up an old MacBook with Ubuntu for Podman for my deep understanding and potential future uses.

            do you recommend testing and learning Podman over Linux, windows or macOS

            what is your suggestion

            thank you

          4. Hey Vijiaselvam,

            I would recommend Podman on Linux. The Windows and macOS ports both come with some sort of embedded Linux VM and hide some of the important details. They are great for getting containers to run but if you want to get a deep understanding for Podman and containers in general, I’d recommend Linux, perhaps even a Linux VM running on a Windows or Mac. 🙂

            Thanks,

          5. Vijiaselvam Nayagam

            Hi Gerald
            Once again it’s refreshing communicating with you.
            Yes I realised that, at my stage of infancy with Podman, when I installed Podman on my M1 MacBook, it fired up a virtual machine and I was confused.

            I think like you said, I will either get a machine to install linux (ubuntu maybe on a VM easier) in my old Intel MacBook and dig deeper into Podman, guess this will be the best option.

            Pi-5 has been put to sleep in it’s box …. ha ha ha
            It does it’s job as an easy method to try some stuff, as easy as plug out & in a micro SD card.

            Thank You very much for your time and support.
            God Bless 🙏

          6. Hi Vijiaselvam,

            I’m glad that I could help! Good luck with your explorations!

            Thanks,

  2. Got it mostly running using docker and this image:

    REPOSITORY TAG IMAGE ID CREATED SIZE
    gvenzl/oracle-free full 635aaefb2b07 4 weeks ago 3.65GB

    I have cgroups memory enabled; 4K PAGESIZE enabled.

    rpi OS version:
    Linux rpi5a 6.6.62+rpt-rpi-v8 #1 SMP PREEMPT Debian 1:6.6.62-1+rpt1 (2024-11-25) aarch64 GNU/Linux

    hardware: 8 GB rpi5. No other configuration changes.
    listener starts fine. DB starts up, changes password. But then:

    Errors in file /opt/oracle/diag/rdbms/free/FREE/trace/FREE_m006_403.trc (incident=529) (PDBNAME=CDB$ROOT):
    ORA-00600: internal error code, arguments: [OSDEP_INTERNAL], [], [], [], [], [], [], [], [], [], [], []
    ORA-27302: failure occurred at: sskgm_mga_at
    Incident details in: /opt/oracle/diag/rdbms/free/FREE/incident/incdir_529/FREE_m006_403_i529.trc

    Searches on Oracle Support and elsewhere have no clue about sskgm_mga_at.

    Very short trace file, the only useful lines seem to be:

    *** 2025-01-15T04:20:15.709231+00:00 (CDB$ROOT(1))
    2025-01-15 04:20:15.708236 : fsd_notify_cb: FsDirect not implemented

    Searches for “fsd_notify_cb” only turned up another user who traced it to a 2 GB memory limit, but /proc/meminfo shows

    MemTotal: 8135708 kBMemFree: 123020 kBMemAvailable: 5509140 kB

    also

    bobby@rpi5a:~ $ docker ps
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
    64c84fc58aab gvenzl/oracle-free:full “container-entrypoin…” 19 minutes ago Up 19 minutes sleepy_elbakyan
    bobby@rpi5a:~ $

    The CDB and PDB are open, and seem to be running fine, but I get the ORA-00600 error in the alert log every “x” minutes or so. Makes me think something is still not configured correctly. Thanks in advance for any possible ideas you may have!

    1. Hi,

      You try disable the oracle parameter _it_memory_cdt=OFF by default is LIMITED

      ORA-27302: failure occurred at: sskgm_mga_at

      docker exec -it your_container /bin/bash

      bash-4.4$ sqlplus / as sysdba

      SQL> alter system set “_disable_memory_cdt”=OFF ;

      Shutdown your database and start your database with docker.

      Check le log by

      docker logs -f your_container

      Regards

      1. Sorry,

        The parameter is _IN_MEMORY_CDT=OFF

        take care this is undercore parameter

        Regards

  3. Gerald, can you tell me the configuration of your rpi5? Such as kernel version? How is the SD card file system formatted? I’ve also tried the new 16GB rpi5 with the latest version of RaspberryPi OS/Debian.

    In every test after configuring cgroups and PAGESIZE per your instructions, I always get ONLY one error using either podman or docker (per my above comment):
    ORA-00600: internal error code, arguments: [OSDEP_INTERNAL]

    I’ve searched every possible Oracle Support note, other Linux/ARM blogs, Oracle user community note. At this point, I’d submit an Oracle Support ticket, but… the developer edition behind your image is officially unsupported. 🙁

    Of course this all started when UEK for ARM is only available for rpi4, and 23ai for ARM only runs on rpi5.

    Any other ideas to try or something that is different about my configuration would be appreciated. I’ve tried both the FULL and the SLIM images. Same behavior. The messages seem to point to something I/O related, such as direct I/O. But there are not many places I can look to see if that’s working. I only have one SD card formatted by the Raspberry Pi Imager with the latest OS kernel version. Thanks again.

  4. Hey Bob,

    I’ll provide the details of my Raspberry Pi 5 tonight when I get a chance to boot it up. I can tell you already that I formatted the Pi with the Raspberry Pi Imager and installed the default Raspberry Pi OS 64-bit on it.

    I’ll also check whether I too see the same errors at my end.

    In the meantime, could you please post the entire trace file, which would help to also see where the error is coming from.

    Thanks,

  5. Hey Bob,

    Here are the details of my Raspberry Pi 5:

    $ cat /etc/os-release
    PRETTY_NAME=”Ubuntu 24.04.1 LTS”
    NAME=”Ubuntu”
    VERSION_ID=”24.04″
    VERSION=”24.04.1 LTS (Noble Numbat)”
    VERSION_CODENAME=noble
    ID=ubuntu
    ID_LIKE=debian
    HOME_URL=”https://www.ubuntu.com/”
    SUPPORT_URL=”https://help.ubuntu.com/”
    BUG_REPORT_URL=”https://bugs.launchpad.net/ubuntu/”
    PRIVACY_POLICY_URL=”https://www.ubuntu.com/legal/terms-and-policies/privacy-policy”
    UBUNTU_CODENAME=noble
    LOGO=ubuntu-logo

    $ uname -a
    Linux gerald-rbp-builder 6.8.0-1016-raspi #18-Ubuntu SMP PREEMPT_DYNAMIC Fri Nov 22 11:55:16 UTC 2024 aarch64 aarch64 aarch64 GNU/Linux

    $ getconf PAGESIZE
    4096

    $ mount | grep ” on / “
    /dev/mmcblk0p2 on / type ext4 (rw,relatime,discard)

    $ cat /boot/firmware/cmdline.txt
    zswap.enabled=1 zswap.zpool=z3fold zswap.compressor=zstd multipath=off dwc_otg.lpm_enable=0 console=tty1 root=LABEL=writable rootfstype=ext4 rootwait fixrtc quiet splash

    I hope this helps!

    Thanks,

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Scroll to Top