{
    "results": [{
            "title": "Llama.cpp with Intel",
            "date": "22 Mar 2026",
            "permalink": "/posts/2026-llama-cpp/",
            "tags": ["llama","ai","intel"],
            "content": "Info Recently bought a Intel Arc B50 and decided to push it to the limits by trying to run some AI models on it\nSetup If you are using proxmox make sure you passthrough the GPU you wish to run AI on\n1 2 3 4 5 features: fuse=1,nesting=1 lxc.cgroup2.devices.allow: c 226:* rwm lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir lxc.mount.entry: /sys/class/drm sys/class/drm none bind,optional,create=dir lxc.mount.entry: tmpfs dev/shm tmpfs rw,nosuid,nodev,size=8192M,create=dir 0 0 For simplicity and ease of upgrade I run this inside a docker compose container to keep it simple. First lets prep the environment with the neccesary packages\n1 2 apt update \u0026amp;\u0026amp; apt install curl intel-gpu-tools curl -L https://get.docker.com |sh Here is the docker-compose.yml I used\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 services: llama: image: ghcr.io/ggml-org/llama.cpp:server-intel container_name: llama restart: unless-stopped cap_add: - IPC_LOCK ports: - 8080:8080 volumes: - ./models:/models - /dev/shm:/dev/shm devices: - /dev/dri/:/dev/dri/ group_add: - \u0026#34;993\u0026#34; # render - \u0026#34;44\u0026#34; # video environment: # Hardware Acceleration SYCL_DEVICE_FILTER: \u0026#34;level_zero:gpu:1\u0026#34; ONEAPI_DEVICE_SELECTOR: \u0026#34;level_zero:*\u0026#34; SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS: \u0026#34;0\u0026#34; SYCL_PI_LEVEL_ZERO_USE_COPY_ENGINE: \u0026#34;1\u0026#34; GGML_SYCL_DEBUG: \u0026#34;0\u0026#34; GGML_SYCL_DEVICE: \u0026#34;1\u0026#34; # Performance Tuning B50 GGML_SYCL_FORCE_MMQ: \u0026#34;1\u0026#34; GGML_SYCL_F16_AS_F32: \u0026#34;0\u0026#34; LLAMA_ARG_FLASH_ATTN: \u0026#34;true\u0026#34; LLAMA_ARG_CACHE_TYPE_K: \u0026#34;f16\u0026#34; LLAMA_ARG_CACHE_TYPE_V: \u0026#34;f16\u0026#34; LLAMA_ARG_BATCH: 1024 LLAMA_ARG_UBATCH: 512 LLAMA_ARG_CHAT_TEMPLATE: \u0026#34;chatml\u0026#34; LLAMA_ARG_JINJA: \u0026#34;true\u0026#34; LLAMA_ARG_PORT: 8080 LLAMA_ARG_MODEL: /models/qwen2.5-coder-14b-instruct-q4_k_m.gguf LLAMA_ARG_MLOCK: true LLAMA_ARG_NO_MMAP: true LLAMA_ARG_N_GPU_LAYERS: \u0026#34;99\u0026#34; Before we start the container make sure you download a model you with to run.\nllama.cpp only supports \u0026ldquo;GGUF\u0026rdquo; models\nDownload models uwint \u0026ldquo;wget\u0026rdquo; from https://huggingface.co/models\nOnce you obtained a model, update teh LLAMA_ARG_MODEL to point to your downloaded file.\nthen run\n1 docker compose up -d once it is running go to page http://your_ip:8080 try a prompt. You can monitor your GPU using gputop\n"
        },{
            "title": "Minio Cluster",
            "date": "15 Mar 2026",
            "permalink": "/posts/2026-minio-cluster/",
            "tags": ["minio","storage","s3"],
            "content": "Info An easy guide to install minio and put in cluster mode\nInstallation First lets prep the environment with the neccesary packages\n1 2 apt update \u0026amp;\u0026amp; apt install curl curl -L https://get.docker.com |sh Here is the docker-compose.yml I used\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 services: minio: container_name: minio image: minio/minio:latest labels: - \u0026#34;traefik.enable=true\u0026#34; - \u0026#34;traefik.http.routers.api.rule=Host(`minio-api.example.com`)\u0026#34; - \u0026#34;traefik.http.routers.api.entrypoints=websecure,web\u0026#34; - \u0026#34;traefik.http.routers.api.tls.certresolver=default\u0026#34; - \u0026#34;traefik.http.routers.api.service=api\u0026#34; - \u0026#34;traefik.http.services.api.loadbalancer.server.port=9000\u0026#34; environment: MINIO_ROOT_USER: minioadmin MINIO_ROOT_PASSWORD: \u0026#34;minio\u0026#34; MINIO_SERVER_URL: https://minio-api.example.com MINIO_VOLUMES: \u0026#34;http://minio1:9000/data http://minio2:9000/data http://minio3:9000/data\u0026#34; volumes: - ./data:/data - ./config:/root/.minio ports: - \u0026#34;9000:9000\u0026#34; networks: - traefik restart: unless-stopped command: [\u0026#34;server\u0026#34;, \u0026#34;/data\u0026#34;] networks: traefik: Repeat this for all 3+ containers with MINIO_VOLUMES pointing to them\nConfiguration Enter into the container\n1 2 3 docker compose exec -it minio bash mc alias set local http://localhost:9000 admin YourStrongPassword123 Create bucket 1 mc mb local/${BUCKET_NAME} --ignore-existing Create user 1 mc admin user add local ${USER} ${PASS} Grant user permission to bucket\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 cat \u0026lt;\u0026lt;POLICY \u0026gt; /tmp/policy.json { \u0026#34;Version\u0026#34;: \u0026#34;2012-10-17\u0026#34;, \u0026#34;Statement\u0026#34;: [ { \u0026#34;Effect\u0026#34;: \u0026#34;Allow\u0026#34;, \u0026#34;Action\u0026#34;: [\u0026#34;s3:*\u0026#34;], \u0026#34;Resource\u0026#34;: [ \u0026#34;arn:aws:s3:::terraform\u0026#34;, \u0026#34;arn:aws:s3:::terraform/*\u0026#34; ] } ] } POLICY mc admin policy create local terraform-policy /tmp/policy.json mc admin policy attach local terraform-policy --user ${USER} "
        },{
            "title": "Gitlab simple pipeline",
            "date": "01 Mar 2026",
            "permalink": "/posts/2026-gitlab-build/",
            "tags": ["docker","kubernetes","sonarqube","gitlab"],
            "content": "Info Here is a simple breakdown of a deployment pipeline which also does quality check using SonarQube\nConfigure .gitlab-ci.yml\n1 2 3 4 5 6 7 8 9 include: - .gitlab/sonarqube.yml - .gitlab/docker-build.yml - .gitlab/deploy.yml stages: - sonar_analysis - build - deploy .gitlab/sonarqube.yml\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 sonarqube-manual-analysis: image: sonarsource/sonar-scanner-cli:latest stage: sonar_analysis cache: key: \u0026#34;$CI_COMMIT_REF_NAME\u0026#34; paths: - .sonar/cache script: - echo \u0026#34;Starting SonarQube analysis on $CI_COMMIT_REF_NAME branch (manual trigger).\u0026#34; - \u0026gt; sonar-scanner -Dsonar.projectKey=$SONAR_PROJECT_KEY -Dsonar.host.url=$SONAR_HOST_URL -Dsonar.token=$SONAR_TOKEN -Dsonar.sources=. -Dsonar.qualitygate.wait=\u0026#34;true\u0026#34; -Dsonar.projectName=$SONAR_PROJECT_KEY allow_failure: true rules: - if: \u0026#39;$CI_COMMIT_BRANCH == \u0026#34;develop\u0026#34; \u0026amp;\u0026amp; $CI_PIPELINE_SOURCE == \u0026#34;push\u0026#34;\u0026#39; when: always .gitlab/docker-build.yml\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 docker_build: stage: build image: docker:24.0.5-cli script: - echo \u0026#34;$CI_REGISTRY_PASSWORD\u0026#34; | docker login $CI_REGISTRY -u $CI_REGISTRY_USER --password-stdin - \u0026#39;[ -n \u0026#34;$CI_COMMIT_TAG\u0026#34; ] \u0026amp;\u0026amp; export FINAL_TAG=$CI_COMMIT_TAG || export FINAL_TAG=${CI_COMMIT_BRANCH}-${CI_COMMIT_SHORT_SHA}\u0026#39; - docker build -t $CI_REGISTRY_IMAGE:$FINAL_TAG -f Dockerfile . - docker push $CI_REGISTRY_IMAGE:$FINAL_TAG - echo \u0026#34;DOCKER_BUILD_URL=$CI_REGISTRY_IMAGE:$FINAL_TAG\u0026#34; \u0026gt; build.env rules: - if: $CI_COMMIT_TAG when: always - if: \u0026#39;$CI_COMMIT_BRANCH == \u0026#34;develop\u0026#34; \u0026amp;\u0026amp; $CI_PIPELINE_SOURCE == \u0026#34;push\u0026#34;\u0026#39; when: always artifacts: reports: dotenv: build.env .gitlab/deploy.yml\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 deploy_dev: stage: deploy image: name: bitnami/kubectl:latest entrypoint: [\u0026#34;\u0026#34;] needs: - docker_build variables: KUBECONFIG: $DEV_KUBECONFIG K8S_NAMESPACE: default K8S_DEPLOYMENT_NAME: api-deployment script: - echo \u0026#34;Set .kube/config\u0026#34; - mkdir -p \u0026#34;${CI_PROJECT_DIR}/.kube\u0026#34; - echo \u0026#34;$KUBECONFIG\u0026#34; | base64 -d \u0026gt; \u0026#34;${CI_PROJECT_DIR}/.kube/config\u0026#34; - export KUBECONFIG=\u0026#34;${CI_PROJECT_DIR}/.kube/config\u0026#34; - echo \u0026#34;Deploying to Kubernetes cluster...\u0026#34; - kubectl config get-contexts - kubectl set image deployment/$K8S_DEPLOYMENT_NAME *=\u0026#34;$DOCKER_BUILD_URL\u0026#34; -n $K8S_NAMESPACE - echo \u0026#34;Deployment updated for $K8S_DEPLOYMENT_NAME in namespace $K8S_NAMESPACE with image $DOCKER_BUILD_URL\u0026#34; - kubectl rollout status deployment/$K8S_DEPLOYMENT_NAME -n $K8S_NAMESPACE rules: - if: \u0026#39;$CI_COMMIT_BRANCH == \u0026#34;develop\u0026#34; \u0026amp;\u0026amp; $CI_PIPELINE_SOURCE == \u0026#34;push\u0026#34;\u0026#39; when: on_success "
        },{
            "title": "Gitlab repo sync",
            "date": "17 Jan 2026",
            "permalink": "/posts/2026-gitlab-sync/",
            "tags": ["gitlab","github","sync"],
            "content": "Pipeline 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 stages: - sync github_sync: stage: sync image: alpine:latest before_script: - apk add git script: - git clone --mirror https://x-access-token:${GITHUB_TOKEN}@github.com/${GITHUB_REPO} ./repo/ - cd repo - git remote set-url --push origin \u0026#34;https://oauth2:${PROJECT_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git\u0026#34; - git push --verbose --mirror rules: - if: $CI_PIPELINE_SOURCE == \u0026#34;schedule\u0026#34; Variables \u0026amp; Config Will need to setup a scheduler for the newly created pipeline\n1 Projects -\u0026gt; [PROJECT_NAME] -\u0026gt; Build -\u0026gt; Pipeline schedules -\u0026gt; New schedule Set \u0026ldquo;Description, Interval pattern\u0026rdquo; and the 2 variables\nGITHUB_REPO\nIf your repo link looks like https://github.com/test/repo1.git then you need to grab the part after the github.com\nExample: test/repo.git\nPROJECT_PUSH_TOKEN\nNeed to generate an API token on Github which has repo scope\n1 Profile -\u0026gt; Settings -\u0026gt; Developer settings -\u0026gt; Personal access tokens -\u0026gt; Tokens (classic) "
        },{
            "title": "LXC Android",
            "date": "08 Nov 2025",
            "permalink": "/posts/2025-lxc-android/",
            "tags": ["android","proxmox"],
            "content": "Proxmox Create a new lxc privileged container with nested feature\nMake sure you dont start the container after creation\nNeed to open the shell on the node where the new container is created\n/etc/pve/lxc/xxx.conf\n1 2 3 lxc.cap.drop: lxc.cgroup.devices.allow: c 10:232 rwm lxc.mount.entry: /dev/kvm dev/kvm none bind,optional,create=file Start the lxc container\nContainer Install Create an installation script\n/root/install.sh\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 #!/bin/bash SDK_ROOT=\u0026#34;$HOME/android-sdk\u0026#34; TOOLS_URL=\u0026#34;https://dl.google.com/android/repository/commandlinetools-linux-13114758_latest.zip\u0026#34; AVD_API_LEVEL=\u0026#34;30\u0026#34; # Target Android API Level (e.g., 30 for Android 11) AVD_SYSTEM_IMAGE=\u0026#34;x86_64\u0026#34; # System image architecture (x86_64 required for KVM acceleration) AVD_NAME=\u0026#34;Headless_Test\u0026#34; dpkg --add-architecture i386 apt update apt install -y unzip wget default-jre-headless \\ libvirt-daemon libvirt-clients cpu-checker \\ libbz2-1.0 libxkbfile1 libncurses5:i386 libstdc++6:i386 lib32z1 mkdir -p \u0026#34;$SDK_ROOT/cmdline-tools/latest\u0026#34; cd \u0026#34;$SDK_ROOT\u0026#34; wget -O sdk-tools.zip \u0026#34;$TOOLS_URL\u0026#34; unzip sdk-tools.zip mv cmdline-tools latest mkdir cmdline-tools mv latest cmdline-tools/ rm sdk-tools.zip grep -qxF \u0026#39;export ANDROID_HOME=\u0026#34;$HOME/android-sdk\u0026#34;\u0026#39; ~/.bashrc || \\ echo \u0026#39;export ANDROID_HOME=\u0026#34;$HOME/android-sdk\u0026#34;\u0026#39; \u0026gt;\u0026gt; ~/.bashrc grep -qxF \u0026#39;export PATH=\u0026#34;$PATH:$ANDROID_HOME/cmdline-tools/latest/bin\u0026#34;\u0026#39; ~/.bashrc || \\ echo \u0026#39;export PATH=\u0026#34;$PATH:$ANDROID_HOME/cmdline-tools/latest/bin\u0026#34;\u0026#39; \u0026gt;\u0026gt; ~/.bashrc grep -qxF \u0026#39;export PATH=\u0026#34;$PATH:$ANDROID_HOME/platform-tools\u0026#34;\u0026#39; ~/.bashrc || \\ echo \u0026#39;export PATH=\u0026#34;$PATH:$ANDROID_HOME/platform-tools\u0026#34;\u0026#39; \u0026gt;\u0026gt; ~/.bashrc source ~/.bashrc SDK_MANAGER=\u0026#34;$ANDROID_HOME/cmdline-tools/latest/bin/sdkmanager\u0026#34; AVD_MANAGER=\u0026#34;$ANDROID_HOME/cmdline-tools/latest/bin/avdmanager\u0026#34; PACKAGES=\u0026#34;platform-tools emulator platforms;android-$AVD_API_LEVEL system-images;android-$AVD_API_LEVEL;default;$AVD_SYSTEM_IMAGE\u0026#34; yes | \u0026#34;$SDK_MANAGER\u0026#34; --licenses \u0026#34;$SDK_MANAGER\u0026#34; $PACKAGES if ! groups | grep -q \u0026#39;kvm\u0026#39;; then usermod -aG kvm \u0026#34;$USER\u0026#34; echo \u0026#34;⚠️ User \u0026#39;$USER\u0026#39; added to the \u0026#39;kvm\u0026#39; group. Please log out and log back in after this script finishes!\u0026#34; fi echo no | \u0026#34;$AVD_MANAGER\u0026#34; create avd -n \u0026#34;$AVD_NAME\u0026#34; -k \u0026#34;system-images;android-$AVD_API_LEVEL;default;$AVD_SYSTEM_IMAGE\u0026#34; echo \u0026#34;--- ✅ Android SDK Setup Complete! ---\u0026#34; echo \u0026#34;You can now launch your emulator instance with a unique port and in headless mode:\u0026#34; echo \u0026#34;emulator -avd $AVD_NAME -no-window -port 5554 \u0026amp;\u0026#34; Run emulator /root/run.sh\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #!/bin/bash EMULATOR_BIN=\u0026#34;$ANDROID_HOME/emulator/emulator\u0026#34; AVD_NAME=\u0026#34;Headless_Test\u0026#34; BASE_PORT=\u0026#34;5554\u0026#34; echo \u0026#34;--- ^=^s Starting Android Emulator \u0026#39;$AVD_NAME\u0026#39; on port $BASE_PORT ---\u0026#34; if [ ! -f \u0026#34;$EMULATOR_BIN\u0026#34; ]; then echo \u0026#34; ^}^l Error: Emulator binary not found at $EMULATOR_BIN.\u0026#34; echo \u0026#34; Ensure you installed the \u0026#39;emulator\u0026#39; package using sdkmanager.\u0026#34; exit 1 fi if [ ! -d \u0026#34;$HOME/.android/avd/$AVD_NAME.avd\u0026#34; ]; then echo \u0026#34; ^}^l Error: AVD \u0026#39;$AVD_NAME\u0026#39; not found.\u0026#34; echo \u0026#34; Ensure you created this AVD using avdmanager.\u0026#34; exit 1 fi \u0026#34;$EMULATOR_BIN\u0026#34; -avd \u0026#34;$AVD_NAME\u0026#34; \\ -no-window \\ -port \u0026#34;$BASE_PORT\u0026#34; \\ -gpu off \\ -qemu -monitor none \\ -no-snapshot-save \u0026amp; sleep 2 ADB_PORT=$((BASE_PORT + 1)) EMU_PID=$(jobs -p | tail -1) echo \u0026#34;--- ^|^e Emulator Started ---\u0026#34; echo \u0026#34;AVD Name: $AVD_NAME\u0026#34; echo \u0026#34;Console Port: $BASE_PORT\u0026#34; echo \u0026#34;ADB Port: $ADB_PORT (Emulator device name: emulator-$ADB_PORT)\u0026#34; echo \u0026#34;Process ID: $EMU_PID\u0026#34; echo \u0026#34;\u0026#34; echo \u0026#34;To connect to this device from your local machine, set up an SSH tunnel:\u0026#34; echo \u0026#34; ssh -N -L 6001:localhost:$ADB_PORT user@your.server.ip\u0026#34; echo \u0026#34;Then, connect locally:\u0026#34; echo \u0026#34; adb connect localhost:6001\u0026#34; "
        },{
            "title": "LXC Rootless docker",
            "date": "07 Oct 2025",
            "permalink": "/posts/2025-proxmox-lxc-rootless-docker/",
            "tags": ["docker","proxmox"],
            "content": "Proxmox Have to update the following file on all proxmox nodes inside the cluster so if HA is enabled this container will be able to run on all\nAll nodes have to have the following config\n/etc/subgid \u0026amp; /etc/subuid\n1 root:100000:262144 Create a new lxc unprivileged container with nested feature for docker Unrprivileged LXC container with debian 13 (tixie)\nMake sure you dont start the container after creation\nNeed to open the shell on the node where the new container is created\n/etc/pve/lxc/xxx.conf\n1 2 3 4 5 6 7 features: fuse=1,keyctl=1,nesting=1 lxc.cgroup.devices.allow: c 10:229 rwm lxc.cgroup2.devices.allow: c 10:200 rwm lxc.mount.entry: /dev/fuse dev/fuse none bind,create=file 0 0 lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file lxc.idmap: u 0 100000 262144 lxc.idmap: g 0 100000 262144 Container Start the container run the following commands as root\n1 2 3 4 5 6 7 8 9 10 apt update apt install -y \\ fuse-overlayfs \\ uidmap \\ curl \\ iptables \\ dbus-user-session useradd -s /bin/bash -m ec2-user loginctl enable-linger ec2-user su ec2-user Following commands as ec2-user\n1 2 3 4 5 6 mkdir -p /home/ec2-user/.config/docker/ echo \u0026#39;{ \u0026#34;storage-driver\u0026#34;: \u0026#34;fuse-overlayfs\u0026#34; }\u0026#39; \u0026gt; /home/ec2-user/.config/docker/daemon.json echo \u0026#39;export XDG_RUNTIME_DIR=/run/user/$(id -u)\u0026#39; \u0026gt;\u0026gt; /home/ec2-user/.bashrc echo \u0026#39;export DBUS_SESSION_BUS_ADDRESS=unix:path=$XDG_RUNTIME_DIR/bus\u0026#39; \u0026gt;\u0026gt; /home/ec2-user/.bashrc exit reboot And reboot so the user systemctl session will start which is a requirement for rootless docker\nLog back in as root and change user to ec2-user\n1 2 3 4 5 6 7 8 9 10 su ec2-user curl -fsSL https://get.docker.com/rootless | sh echo \u0026#39;export DOCKER_HOST=unix://$XDG_RUNTIME_DIR/docker.sock\u0026#39; \u0026gt;\u0026gt; /home/ec2-user/.bashrc echo \u0026#39;export PATH=/home/ec2-user/bin:$PATH\u0026#39; \u0026gt;\u0026gt; /home/ec2-user/.bashrc DOCKER_COMPOSE_DIR=\u0026#34;$HOME/.docker/cli-plugins\u0026#34; COMPOSE_VERSION=\u0026#34;v2.39.4\u0026#34; ARCH=$(uname -m) mkdir -p \u0026#34;$DOCKER_COMPOSE_DIR\u0026#34; curl -SL \u0026#34;https://github.com/docker/compose/releases/download/$COMPOSE_VERSION/docker-compose-linux-$ARCH\u0026#34; -o \u0026#34;$DOCKER_COMPOSE_DIR/docker-compose\u0026#34; chmod +x \u0026#34;$DOCKER_COMPOSE_DIR/docker-compose\u0026#34; Now you are ready to start any containers as a non-root user in an unprivileged lxc container\n"
        },{
            "title": "Postgres handy commands",
            "date": "04 Oct 2025",
            "permalink": "/posts/2025-postgres/",
            "tags": ["postgres","database","sql"],
            "content": "User management Create 1 2 3 4 5 -- With login -- CREATE USER my_pg_user WITH PASSWORD \u0026#39;your_secure_password\u0026#39;; -- No login -- CREATE ROLE my_pg_user WITH LOGIN PASSWORD \u0026#39;strong_password\u0026#39;; Update 1 2 3 4 5 -- Update password for a specific user ALTER USER \u0026#39;my_pg_user\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED BY \u0026#39;new_secure_password\u0026#39;; -- If you are updating your OWN password SET PASSWORD = PASSWORD(\u0026#39;new_secure_password\u0026#39;); Delete 1 DROP USER IF EXISTS \u0026#39;my_pg_user\u0026#39;@\u0026#39;localhost\u0026#39;; Privileges Admin privileges 1 2 3 GRANT CONNECT ON DATABASE my_database TO my_pg_user; GRANT USAGE ON SCHEMA my_database TO my_pg_user; GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA my_database TO my_pg_user; Revoke public access 1 REVOKE CONNECT ON DATABASE my_database FROM PUBLIC; Limited access 1 2 3 ALTER DEFAULT PRIVILEGES IN SCHEMA my_database; GRANT ALL PRIVILEGES ON TABLES my_database TO my_pg_user; GRANT SELECT ON TABLE customers, orders TO my_pg_user; "
        },{
            "title": "Mariadb handy commands",
            "date": "11 Sep 2025",
            "permalink": "/posts/2025-mariadb/",
            "tags": ["mariadb","database","sql"],
            "content": "User management Create When creating user make use you replace localhost to the ip the client can access from or add % if you allow global access\n1 CREATE USER \u0026#39;username\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED BY \u0026#39;strong_password\u0026#39;; Update 1 ALTER USER username WITH PASSWORD \u0026#39;new_password\u0026#39;; Delete 1 DROP USER IF EXISTS username; Privileges Admin privileges 1 2 GRANT ALL PRIVILEGES ON my_database.* TO \u0026#39;username\u0026#39;@\u0026#39;localhost\u0026#39;; FLUSH PRIVILEGES; Limited access 1 2 3 GRANT SELECT ON my_database.table1 TO \u0026#39;username\u0026#39;@\u0026#39;localhost\u0026#39;; GRANT SELECT ON my_database.table2 TO \u0026#39;username\u0026#39;@\u0026#39;localhost\u0026#39;; FLUSH PRIVILEGES; Database Create 1 CREATE DATABASE database_name; "
        },{
            "title": "LXC GPU passthrough",
            "date": "06 Sep 2025",
            "permalink": "/posts/2025-lxc-gpu-passthrough/",
            "tags": ["media","proxmox","ai"],
            "content": "GPU passthrough can be useful for media encodings, AI or other GPU required tasks\nUpdate config Simply update the lxc container config\n/etc/pve/lxc/xxx.conf\n1 2 3 4 lxc.cgroup2.devices.allow: c 226:0 rwm lxc.cgroup2.devices.allow: c 226:128 rwm lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file "
        },{
            "title": "Mongodb handy commands",
            "date": "30 Jul 2025",
            "permalink": "/posts/2025-mongodb/",
            "tags": ["mongodb","database"],
            "content": "Connect 1 mongosh --host localhost:27017 -u admin -p xxxxxxxx --authenticationDatabase admin User management Create 1 2 3 4 5 db.createUser({ user: \u0026#34;username\u0026#34;, pwd: \u0026#34;password\u0026#34;, roles: [{ role: \u0026#34;readWrite\u0026#34;, db: \u0026#34;database\u0026#34; }], }); Update 1 2 3 db.updateUser(\u0026#34;username\u0026#34;, { pwd: \u0026#34;password\u0026#34;, }); Delete 1 db.dropUser(\u0026#34;username\u0026#34;); Change Password 1 db.changeUserPassword(\u0026#34;username\u0026#34;, \u0026#34;password\u0026#34;); Privileges 1 2 3 4 5 6 7 8 9 10 11 12 13 14 db.createRole({ role: \u0026#34;readSpecificCollections\u0026#34;, privileges: [ { resource: { db: \u0026#34;my_database\u0026#34;, collection: \u0026#34;products\u0026#34; }, actions: [\u0026#34;find\u0026#34;], }, { resource: { db: \u0026#34;my_database\u0026#34;, collection: \u0026#34;inventory\u0026#34; }, actions: [\u0026#34;find\u0026#34;], }, ], roles: [], }); "
        },{
            "title": "Networking macvlan",
            "date": "10 Mar 2025",
            "permalink": "/posts/2025-macvlan/",
            "tags": ["networking","linux"],
            "content": "When setting up macvlan for docker meaning each container can get an external IP on our local network. Also need to make sure those containers can communicate with each other\nTemporary We want to achieve the following in macvlan, however this is only a temporary solution as config will disappear after a reboot.\n1 2 3 4 ip link add macvlan link eth0 type macvlan mode bridge ip addr add ${GATEWAY_IP} dev macvlan ip link set macvlan up ip route add ${MACVLAN1_IP |- 172.16.31.11} dev macvlan Permanent Need to create a file which on startup will create a macvlan bridge\n/etc/networkd-dispatcher/routable.d/10-macvlan-interfaces.sh\n1 2 3 #! /bin/bash ip link add macvlan link eth0 type macvlan mode bridge Now we got an interface, will need to create mapping for the docker containers we want to map\n/etc/netplan/macvlan.yaml\n1 2 3 4 5 6 7 8 9 10 11 network: version: 2 renderer: networkd ethernets: macvlan0: addresses: - 172.16.31.5/32 routes: - to: ${MACVLAN1_IP |- 172.16.31.11} via: ${GATEWAY_IP} metric: 100 Docker Now we can create a macvlan network\n1 2 3 4 5 6 docker network create -d macvlan \\ --subnet=172.16.31.0/24 \\ --gateway=172.16.31.1 \\ --ip-range=172.16.31.48/28 \\ -o parent=eth0 \\ my_macvlan_net example lunching a docker container\n1 docker run -d --name test --network my_macvlan_net --ip 172.16.31.11 nginx "
        },{
            "title": "Jellyfin install",
            "date": "03 Nov 2024",
            "permalink": "/posts/2024-jellyfin/",
            "tags": ["jellyfin","media","proxmox"],
            "content": "Proxmox Create a new lxc privileged container with nested feature for docker\nMake sure you dont start the container after creation\nNeed to open the shell on the node where the new container is created\n/etc/pve/lxc/xxx.conf\n1 2 3 4 lxc.cgroup2.devices.allow: c 226:0 rwm lxc.cgroup2.devices.allow: c 226:128 rwm lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file Start the lxc container\nContainer Will need to install Docker as root\n1 2 3 4 5 apt install curl curl -fsSL https://get.docker.com | sh useradd -s /bin/bash -m ec2-user usermod -aG docker ec2-user su ec2-user run the following commands as user\n1 2 3 4 cd mkdir /home/ec2-user/config mkdir /home/ec2-user/cache touch /home/ec2-user/docker-compose.yml Update the compose file\n/home/ec2-user/docker-compose.yml\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 services: jellyfin: image: jellyfin/jellyfin:10.11.1 container_name: jellyfin user: 1000:1000 group_add: - \u0026#34;993\u0026#34; ports: - 8096:8096/tcp - 7359:7359/udp volumes: - ./config:/config - ./cache:/cache - type: bind source: ./media target: /media read_only: true devices: - /dev/dri/renderD128:/dev/dri/renderD128 - /dev/dri/card0:/dev/dri/card0 restart: \u0026#34;unless-stopped\u0026#34; environment: - JELLYFIN_PublishedServerUrl=https://jellyfin.service then start jellyfin\n1 docker compose up -d Verify video encoding 1 2 docker exec -it jellyfin /usr/lib/jellyfin-ffmpeg/vainfo docker exec -it jellyfin /usr/lib/jellyfin-ffmpeg/ffmpeg -v verbose -init_hw_device vaapi=va -init_hw_device opencl@va "
        },{
            "title": "Nginx Load Balancer",
            "date": "12 Aug 2024",
            "permalink": "/posts/2024-nginx-lb/",
            "tags": ["nginx","load balancing"],
            "content": "In the following example I will have a load balancing setup with 3 kubernetes nodes which has Traefik running on port 80 and port 443\nInstall 1 2 apt update apt install -y nginx Configure Update the nginx configuration file\n/etc/nginx/nginx.conf\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 768; } http { upstream node_servers { server 10.10.1.10; server 10.10.1.11; server 10.10.1.12; } server { listen 80; listen [::]:80; server_name _; proxy_http_version 1.1; proxy_set_header HOST $host; proxy_set_header X-Forwarded_Host $host; proxy_set_header X-Forwarded_For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection \u0026#34;upgrade\u0026#34;; location / { proxy_pass http://node_servers; } } } include /etc/nginx/passthrough.conf; /etc/nginx/passthrough.conf\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 stream { upstream https_servers { server 10.10.1.10:443 max_fails=3 fail_timeout=30s; server 10.10.1.11:443 max_fails=3 fail_timeout=30s; server 10.10.1.12:443 max_fails=3 fail_timeout=30s; } server { listen 443; proxy_pass https_servers; proxy_next_upstream on; ssl_preread on; } } "
        },{
            "title": "Cloudflare ddns",
            "date": "11 Sep 2023",
            "permalink": "/posts/2023-cf-ddclient/",
            "tags": ["cloudflare","dns"],
            "content": "Cloudflare From cloudflare we need to generate an API token which we will use later for dynamicly update the our public IP for the A record for the selected domain\nCreate API token Open cloudflare dashboard, go to the “API Tokens” section your Cloudflare profile to create a token.\nYour new token needs to have:\nthe Zone:DNS:Read permission (not automatically granted in the Write permission) the Zone:DNS:Write permission the “All zones from an account” scope Save the token as you will need it in the following steps\nLinux Setup a basic linux server or vm, I will carry on with a debian setup\nInstall the latest version of ddclient Run the following commands\n1 2 apt update apt install -y ddclient Configuration ddclient is controlled by ddclient.conf which we will need to modify\nUpdate \u0026ldquo;$EMAIL\u0026rdquo;, \u0026ldquo;$PASSWORD\u0026rdquo; and \u0026ldquo;$HOST\u0026rdquo; in\n\u0026ldquo;PASSWORD\u0026rdquo; is the API Token we generated before\n/etc/ddclient.conf\n1 2 3 4 5 6 protocol=cloudflare \\ use=web, web=https://api.ipify.org/ \\ login=\u0026#39;$EMAIL\u0026#39; \\ password=\u0026#39;$PASSWORD\u0026#39; \\ zone=\u0026#39;$HOST\u0026#39; \\ $HOST Restart ddclient service\n1 systemctl restart ddclient.service "
        },{
            "title": "K3S Cluster creation",
            "date": "23 Jul 2023",
            "permalink": "/posts/2023-k3s/",
            "tags": ["proxmox","kubernetes"],
            "content": "Proxmox Create a new lxc privileged container with nested feature for docker\nMake sure you dont start the container after creation\nNeed to open the shell on the node where the new container is created\n/etc/pve/lxc/xxx.conf\n1 2 3 4 lxc.apparmor.profile: unconfined lxc.cgroup.devices.allow: a lxc.cap.drop: lxc.mount.auto: \u0026#34;proc:rw sys:rw\u0026#34; Start the lxc container\nContainer 1 2 3 4 5 6 apt update \u0026amp;\u0026amp; apt upgrade -y \u0026amp;\u0026amp; apt install curl nfs-common-y echo \u0026#39;#!/bin/sh -e ln -s /dev/console /dev/kmsg mount - make-rshared /\u0026#39; \u0026gt; /etc/rc.local chmod +x /etc/rc.local reboot After restart log back into the lxc container and install K8S\nThis setup requires an external mysql to be used\n1 2 3 4 5 6 curl -sfL https://get.k3s.io | sh -s - server \\ --token=TOKEN \\ --tls-san=10.10.0.1 \\ --datastore-endpoint=\u0026#34;mysql://kubernetes:$PASSWORD@tcp($MYSQL_HOST:3306)/kubernetes\u0026#34; \\ --cluster-cidr=172.16.0.0/16 \\ --disable=traefik "
        }]
}
