Author: Walter Macomber

  • Docker + RabbitMQ

    RabbitMQ is a Message Queue system (hence: MQ). Consider it a message bus, where things can pop messages onto the bus and other things can consume those same messages. The uptick is that as long as something is able to connect to the message bus, it can talk to everything else on that same bus.

    First, some pre-setup:

    $ echo "[rabbitmq_federation_management,rabbitmq_management,rabbitmq_prometheus,rabbitmq_web_dispatch,rabbitmq_management_agent]." > enabled_plugins

    Then:

    $ mkdir conf.d

    So now we have a file with a list of plugins we’d like enabled, and an empty directory called conf.d. Next, let’s build our docker-compose.yml file:

    services:
      rabbitmq:
        image: rabbitmq:latest
        restart: always
        ports:
    # MQTT - uncomment next line to use
    #      - 1883:1883
          - 5672:5672
          - 15672:15672
          - 15692:15692
    # STOMP - uncomment next line to use
    #      - 61613:61613
        environment:
          RABBITMQ_DEFAULT_USER: admin
          RABBITMQ_DEFAULT_PASS: password
        volumes:
          - rabbitmq-data:/var/lib/rabbitmq
          - ./enabled_plugins:/etc/rabbitmq/enabled_plugins
          - ./conf.d:/etc/rabbitmq/conf.d
    
    volumes:
      rabbitmq-data:
        external: false

    Be sure to update the environment variables RABBITMQ_DEFAULT_USER and RABBITMQ_DEFAULT_PASS to suit your needs – these are the credentials you’ll use to log into the web interface on port 5672, so keep them safe.

    This setup uses docker’s built-in volumes for storage, but gives the user an easy way to change the plugins used by the docker container and to tweak other configuration variables.

  • Docker + Graylog

    Graylog is a handy, free log aggregator. This is a simple way to start using their open source offering in a hurry. We’ll start with the assumption that you have a system with docker installed, and that you have access to use it.

    Use the following command to create your GRAYLOG_DATANODE_PASSWORD_SECRET:

    $ < /dev/urandom tr -dc A-Z-a-z-0-9 | head -c${1:-96};echo;
    This will ultimately output 96 random characters that consist of A-Z, a-z, 0-9, and the literal “-” character…

    (What’s really going on here? If you try the command to the left of the pipe, you’ll find that it spits random text out to your terminal until you hit CTRL-C. The command to the right of the pipe takes 96 characters from that output and prints them to the terminal for you.)

    Then, create your GRAYLOG_DATANODE_ROOT_PASSWORD_SHA2:

    $ echo -n "Enter Password: " && head -1 </dev/stdin | tr -d '\n' | sha256sum | cut -d" " -f1

    This will prompt you for a password (which will appear in your terminal session, but not in your history), which it will convert into a SHA256 hash and print to the console.

    Now create your docker-compose.yml file:

    services:
      # MongoDB: https://hub.docker.com/_/mongo/
      mongodb:
        image: "mongo:6.0.18"
        restart: "on-failure"
        networks:
          - graylog
        volumes:
          - "mongodb_data:/data/db"
          - "mongodb_config:/data/configdb"
      # Graylog Data Node: https://hub.docker.com/r/graylog/graylog-datanode
      datanode:
        image: "graylog/graylog-datanode:6.1"
        hostname: "datanode"
        environment:
          GRAYLOG_DATANODE_NODE_ID_FILE: "/var/lib/graylog-datanode/node-id"
          GRAYLOG_DATANODE_PASSWORD_SECRET: "GENERATEME"
          GRAYLOG_DATANODE_ROOT_USERNAME: "admin"
          GRAYLOG_DATANODE_ROOT_PASSWORD_SHA2: "GENERATEME"
          GRAYLOG_DATANODE_MONGODB_URI: "mongodb://mongodb:27017/graylog"
        ulimits:
          memlock:
            hard: -1
            soft: -1
          nofile:
            soft: 65536
            hard: 65536
        networks:
          - graylog
        volumes:
          - "graylog-datanode:/var/lib/graylog-datanode"
        restart: "on-failure"
      # Graylog: https://hub.docker.com/r/graylog/graylog/
      graylog:
        hostname: "server"
        image: "graylog/graylog:6.1"
        depends_on:
          mongodb:
            condition: "service_started"
          datanode:
            condition: "service_started"
        entrypoint: "/usr/bin/tini -- /docker-entrypoint.sh"
        environment:
          GRAYLOG_NODE_ID_FILE: "/usr/share/graylog/data/config/node-id"
          GRAYLOG_HTTP_BIND_ADDRESS: "0.0.0.0:9000"
          GRAYLOG_MONGODB_URI: "mongodb://mongodb:27017/graylog"
          # To make reporting (headless_shell) work inside a Docker container
          GRAYLOG_REPORT_DISABLE_SANDBOX: "true"
          # CHANGE ME (must be at least 16 characters)!
          GRAYLOG_PASSWORD_SECRET: "USE GRAYLOG_DATANODE_PASSWORD_SECRET"
          # Password: "admin"
          GRAYLOG_ROOT_PASSWORD_SHA2: "USE GRAYLOG_DATANODE_ROOT_PASSWORD_SHA2"
          GRAYLOG_HTTP_EXTERNAL_URI: "http://127.0.0.1:9000/"
        ports:
          # Graylog web interface and REST API
          - "9000:9000/tcp"
          # Beats
          - "5044:5044/tcp"
          # Syslog TCP
          - "5140:5140/tcp"
          # Syslog UDP
          - "5140:5140/udp"
          # GELF TCP
          - "12201:12201/tcp"
          # GELF UDP
          - "12201:12201/udp"
          # Forwarder data
          - "13301:13301/tcp"
          # Forwarder config
          - "13302:13302/tcp"
        restart: "on-failure"
        networks:
          - graylog
        volumes:
          - "graylog_data:/usr/share/graylog/data"
    networks:
      graylog:
        driver: "bridge"
    volumes:
      mongodb_data:
      mongodb_config:
      graylog-datanode:
      graylog_data:

    Now all you have to do is bring the containers up and wait for them to initialize:

    $ docker compose up -d && docker compose logs -f

    This will pull the images (if you haven’t already), build the containers, and start them, then it will stream the logs from your containers to the console so you can watch them come up. When you are satisfied, you can press CTRL-C to stop the log stream; your containers will still be running in the background, you can use the command docker compose ps to see the current status of your pods and the network ports they are using.

    Regarding network ports, entries that look like “27017/tcp” indicate that the port is only open to other docker containers and not to the host machine. Entries that look like “0.0.0.0:9000->9000/tcp” (IPv4) or “:::9000->9000/tcp” (IPv6) indicate that these ports can be seen by the host.

    To bring everything down, simply type:

    $ docker compose down

  • Digestives

    Homemade version of McVitie’s Digestive Biscuit. Since they’ve become hard to find (at least, during the pandemic) I’ve made my own; they’re a component of another recipe in our home.

    • 1 2/3 cups flour (whole wheat)
    • 1 tsp baking powder
    • 1/2 tsp salt
    • (up to) 2/3 cup powdered sugar
    • 1/2 cup butter (cut into little cubes)
    • 1/8 cup coconut milk
    • 1/8 cup heavy cream

    Prepare a baking sheet, lay down some parchment paper. Preheat the oven to 350 degrees F.

    Combine flour, baking powder, salt, and sugar. Mix in butter cubes thoroughly; you’re kind of making pie crust here. At least, that’s how it should feel. Mix the coconut milk and heavy cream (really, you just need about 1/4 cup of milk-ish liquid) slowly into the mixture. (You want dough, not dry crumbles, and not soup.) Roll the dough so it’s about 1/8″ thick (like the aforementioned Digestives). Cut them into whatever size and shape you want (the mouth of a drinking glass works well). Put them onto your prepared baking sheet. Use a fork to poke holes part-way into the dough. Bake for 20-25 minutes (depending on your oven). They should be firm and slightly browned when done.

  • Banana Bread

    • 1 cup sugar
    • 1 stick butter
    • 2 eggs
    • 2 cups flour
    • 3 ripe bananas
    • 1 tsp salt
    • 1 tsp baking soda
    • 1 tsp vanilla

    Mix ingredients well. Bake in bread pan at 350 degrees F for 55 minutes. Remove from pan and cool on wire rack.

    If you want to get really fancy, you can start the caramelization process for the sugars in the bananas by baking them before mixing them into the batter. Put the bananas in an oven-safe pan, stab a few holes in each, and bake them for 20 minutes at 325 degrees F. You’re really just melting the sugar at this point, but it makes the bread better, dammit. Be careful you don’t cook the eggs in the mix before you mean to!

  • Crรจme Brรปlรฉe

    • 3 3/4 cup whole milk
    • 1 2/3 cup heavy cream
    • 1 tsp loose tea
    • 3/4 cup baker’s sugar
    • 8 egg yolks
    • raw brown sugar (and a torch) for topping

    Bring milk and cream to a boil. Add tea leaves and infuse, covered, for no more than 4 minutes.

    Mix sugar and egg yolks. Add to infused milk. Strain.

    Refrigerate mixture until cool. (at least an hour)

    Divide custard among ramekins and place ramekins in a baking dish.

    Fill baking dish with hot water until water reaches 1/2 to 2/3 of the way up the ramekins. Cover dish with a cookie sheet (don’t use aluminum foil).

    Bake at 350 degrees F until the center of the custards is set (70 to 75 minutes). Allow baking dish to cool. Remove ramekins and refrigerate at least 3 hours. If water condenses on top, blot with a paper towel.

    Just before serving, sprinkle with brown sugar and caramelize with torch.

    (I think next time, I should try to infuse the sugar with the tea, which would consist of putting the sugar into a small container and mixing the tea into it, then letting it sit.)