diff --git a/.gitmodules b/.gitmodules index 74d53404..8f4a4da8 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,12 @@ [submodule "themes/anubis"] path = themes/anubis url = https://github.com/mitrichius/hugo-theme-anubis.git +[submodule "themes/black-and-light"] + path = themes/black-and-light + url = https://github.com/davidhampgonsalves/hugo-black-and-light-theme.git +[submodule "themes/anubis2"] + path = themes/anubis2 + url = https://github.com/Junyi-99/hugo-theme-anubis2.git +[submodule "themes/hugo-coder"] + path = themes/hugo-coder + url = https://github.com/rnemeth90/hugo-coder.git diff --git a/Screenshot 2024-09-04 at 11.13.40.png b/Screenshot 2024-09-04 at 11.13.40.png new file mode 100644 index 00000000..284f1d92 Binary files /dev/null and b/Screenshot 2024-09-04 at 11.13.40.png differ diff --git a/config.toml b/config.toml new file mode 100644 index 00000000..e1c3ae08 --- /dev/null +++ b/config.toml @@ -0,0 +1,109 @@ +languageCode = "en-us" +name = "GeekyRyan" +baseUrl = "https://rnemeth90.github.io" +title = "GeekyRyan" +theme = "hugo-coder" +paginate = 10 +enableRobotsTXT = true + +[pagination] +pagerSize = 10 # Added field from Coder theme + +[services] +[services.disqus] +# Enable Disqus comments +# shortname = "yourdiscussshortname" # Added section from Coder theme + +[markup.highlight] +style = "base16-snazzy" +noClasses = false # Added field from Coder theme + +[markup.goldmark.renderer] +unsafe = true # enable raw HTML in Markdown + +[params] +author = "Ryan Nemeth" +email = "ryannemeth@live.com" # used for microformats +avatar = "/images/bobble.jpg" # used for microformats +description = "Ryan Nemeth's personal website" +keywords = "blog,developer,personal,devops" +info = ["Full Stack DevOps Engineer"] +avatarURL = "images/bobble.jpg" # +dateFormat = "2006-01-02" +name = "GeekyRyan" +paginationSinglePost = true +style = "dark" +readMore = true # show read more button +readNextPosts = 5 # show 5 related posts, 0 by default +disableSummary = false +copyCodeButton = true # true by default +rssAsSocialIcon = true +since = 2012 +rtl = false # Added from Coder theme +colorScheme = "auto" # Added from Coder theme +hideColorSchemeToggle = false # Added from Coder theme +maxSeeAlsoItems = 5 # Added from Coder theme +customCSS = [] # Added from Coder theme +customSCSS = [] # Added from Coder theme +customJS = [] # Added from Coder theme +customRemoteJS = [] # Added from Coder theme + +[[params.social]] +url = "https://github.com/rnemeth90/" +name = "Github" +icon = "fa-brands fa-github fa-2x" +weight = 1 + +# [[params.social]] +# name = "Twitter" +# icon = "fa-brands fa-x-twitter fa-2x" +# weight = 3 +# url = "https://twitter.com/johndoe/" # Added from Coder theme + +[[params.social]] +name = "LinkedIn" +icon = "fa-brands fa-linkedin fa-2x" +weight = 2 +url = "https://www.linkedin.com/in/ryan-nemeth-b0b1504b/" + +[[params.social]] +name = "RSS" +icon = "fa-solid fa-rss fa-2x" +weight = 3 +url = "https://rnemeth90.github.io/index.xml" +rel = "alternate" +type = "application/rss+xml" # Added from Coder theme + +[taxonomies] +category = "categories" +tag = "tags" +series = "series" # Added from Coder theme +author = "authors" # Added from Coder theme + +[languages.en] +languageName = ":uk:" + +[[languages.en.menu.main]] +name = "About" +weight = 1 +url = "about/" + +[[languages.en.menu.main]] +name = "Blog" +weight = 2 +url = "posts/" + +[[languages.en.menu.main]] +name = "Projects" +weight = 3 +url = "projects/" + +[[languages.en.menu.main]] +name = "Tags" +url = "/tags/" +weight = 4 + +# [[languages.en.menu.main]] +# name = "Contact me" +# weight = 5 +# url = "contact/" diff --git a/config.yaml b/config.yaml deleted file mode 100644 index 23e04047..00000000 --- a/config.yaml +++ /dev/null @@ -1,85 +0,0 @@ -languageCode: "en-us" -baseUrl: "https://rnemeth90.github.io" -title: "GeekyRyan" -theme: "github.com/Mitrichius/hugo-theme-anubis" -paginate: 10 -#disqusShortname: "yourdiscussshortname" -#googleAnalytics: "G-12345" -enableRobotsTXT: true - -menu: - main: - - identifier: archive - name: Archive - title: Archive - url: /posts/ - weight: 3 - - identifier: about - name: About - title: about - url: /about - weight: 1 - - identifier: tags - name: Tags - title: tags - url: /tags/ - weight: 2 - -taxonomies: - category: "categories" - tag: "tags" - -params: - author: "Ryan Nemeth" - email: ryannemeth@live.com # used for microformats - avatar: "/images/bobble.jpg" # used for microformats - description: "" - # Uncomment if you need this - # images: - # - images/og-featured.png # relative path to "static" directory - # customCSS: - # - css/my.css # relative path to "assets" directory (don't use main.css filename) - # customJS: - # - js/main.js # relative path to "assets" directory - dateFormat: "2006-01-02" - paginationSinglePost: true - style: dark - readMore: true # show read more button - readNextPosts: 5 # show 5 related posts, 0 by default - disableSummary: false - copyCodeButton: true # true by default - rssAsSocialIcon: true - # utteranc.es support - utterancesRepo: "" # mandatory - utterancesTheme: "" # optional - utterancesIssue: "" # optional - utterancesLabel: "" # optional - # isso support - isso: - enabled: true # mandatory - data: "https://comments.example.com/" # mandatory - jsLocation: "https://comments.example.com/js/embed.min.js" # mandatory - css: true # optional - lang: "de" # optional - replyToSelf: true # mandatory - requireAuthor: true # mandatory - requireEmail: true # mandatory - id: "thread-id" # optional - avatar: true # optional - avatar-bg: "#f0f0f0" # optional - feed: false # optional - graphcommentId: "" - webmentions: - url: https://yourdomain.com/webemntions/receive - login: hugo-theme-anubis - pingback: true - social: - - id: github - name: rnemeth90 - - id: twitter - name: geeky_ryan - -markup: - goldmark: - renderer: - unsafe: true # enable raw HTML in Markdown diff --git a/config.yaml.old b/config.yaml.old new file mode 100644 index 00000000..90d32c90 --- /dev/null +++ b/config.yaml.old @@ -0,0 +1,72 @@ +languageCode: 'en-us' +name: 'GeekyRyan' +baseUrl: 'https://rnemeth90.github.io' +title: 'GeekyRyan' +theme: 'anubis2' +paginate: 10 +enableRobotsTXT: true + +menu: + main: + - identifier: archive + name: Archive + title: Archive + url: /posts/ + weight: 3 + - identifier: about + name: About + title: about + url: /about + weight: 1 + - identifier: tags + name: Tags + title: tags + url: /tags/ + weight: 2 + +taxonomies: + category: 'categories' + tag: 'tags' + +params: + author: 'Ryan Nemeth' + email: ryannemeth@live.com # used for microformats + avatar: '/images/bobble.jpg' # used for microformats + description: '' + dateFormat: '2006-01-02' + name: 'GeekyRyan' + paginationSinglePost: true + style: dark + readMore: true # show read more button + readNextPosts: 5 # show 5 related posts, 0 by default + disableSummary: false + copyCodeButton: true # true by default + rssAsSocialIcon: true + utterancesRepo: '' # mandatory + utterancesTheme: '' # optional + utterancesIssue: '' # optional + utterancesLabel: '' # optional + isso: + enabled: true # mandatory + data: 'https://comments.example.com/' # mandatory + jsLocation: 'https://comments.example.com/js/embed.min.js' # mandatory + css: true # optional + lang: 'de' # optional + replyToSelf: true # mandatory + requireAuthor: true # mandatory + requireEmail: true # mandatory + id: 'thread-id' # optional + avatar: true # optional + avatar-bg: '#f0f0f0' # optional + feed: false # optional + graphcommentId: '' + social: + - id: github + name: rnemeth90 + +markup: + highlight: + style: 'base16-snazzy' + goldmark: + renderer: + unsafe: true # enable raw HTML in Markdown diff --git a/content/images/acr-403-02.png b/content/images/acr-403-02.png new file mode 100644 index 00000000..284f1d92 Binary files /dev/null and b/content/images/acr-403-02.png differ diff --git a/content/images/acr-403.png b/content/images/acr-403.png new file mode 100644 index 00000000..0202193d Binary files /dev/null and b/content/images/acr-403.png differ diff --git a/content/posts/2024-03-27-golang-detect-file-type.md b/content/posts/2024-03-27-golang-detect-file-type.md new file mode 100644 index 00000000..7c14daf2 --- /dev/null +++ b/content/posts/2024-03-27-golang-detect-file-type.md @@ -0,0 +1,56 @@ +--- +title: 'Detecting MIME Types in Go' +author: Ryan +date: '2024-03-27' +layout: post +draft: false +categories: + - golang + - web development + - software development +tags: + - golang + - web development + - software development + - url +--- + +# Introduction + +Knowing the type of a file you're working with is not just a matter of curiosity — it's often a necessity. This is especially true when you're deciding whether or not a particular operation can be carried out on that file. Go, with its comprehensive standard library, offers a straightforward approach to identifying a file's MIME type, ensuring that developers have the tools they need to make informed decisions about file manipulation. You may expect to find this functionality in the `file` package, but you'd be wrong! Read on... + +## The net/http Package: Your Gateway to MIME Detection + +At the heart of Go's approach to MIME type detection is the `net/http` package. This package provides everything developers need for identifying file types. The method in question, `DetectContentType()`, is nothing short of a detective dedicated to uncovering the secrets held within the first 512 bytes of a file. + +Imagine you're downloading an image for processing from a URL, but before you proceed, you need to confirm its type. Here's how you'd *go* about it: + +``` +resp, err := client.Get("https://rnemeth90.github.io/images/synology-cloud-sync-01.png") +if err != nil { + log.Fatal(err) +} +defer resp.Body.Close() + +bytes, err := ioutil.ReadAll(resp.Body) +if err != nil { + log.Fatal(err) +} + +// detecting the MIME type +mimeType := http.DetectContentType(bytes) +fmt.Println(mimeType) // Voila! It's an image/png +``` + +In this snippet, `DetectContentType()` takes the stage, examining the initial bytes of the file and returning a MIME type, such as `image/png`. Should it find itself at a loss, unable to pin down the file's type, it defaults to `application/octet-stream`, a way of saying, "This is a file, but beyond that, you're on your own." + +# Beyond the Basics: When You Need More + +While `DetectContentType()` serves well for a number of common file types, its repertoire is not unlimited. There are scenarios where you might find yourself needing to identify more obscure or specific file types. This is where the mimetype library steps in, offering a more extensive catalog of file types. If `DetectContentType()` isn't able to help you, considering this library might just be your next move. + +# Conclusion + +Go's `net/http` package, with its `DetectContentType()` method, provides a solid foundation for this task. And for those times when you need to *go* further, the `mimetype` library is there to help. + +Whether you're safeguarding against the wrong file types in an upload process or curating content based on its nature, understanding and utilizing MIME type detection is an invaluable skill. Thanks for reading! + diff --git a/content/posts/2024-06-29-mount multiple Kubernetes secrets into one directory.md b/content/posts/2024-06-29-mount multiple Kubernetes secrets into one directory.md new file mode 100644 index 00000000..4cdf9582 --- /dev/null +++ b/content/posts/2024-06-29-mount multiple Kubernetes secrets into one directory.md @@ -0,0 +1,68 @@ +--- +title: 'Mounting Multiple Kubernetes Secrets into One Directory' +author: Ryan +date: '2024-06-29' +layout: post +draft: false +categories: + - Kubernetes +tags: + - devops + - web development + - software development +--- + +# Introduction + +Combining multiple Kubernetes secrets into a single directory can streamline secret management in your applications. This guide walks you through the process of achieving this in Kubernetes, ensuring efficient and organized secret management. + +# Creating Secrets + +First, create your secrets using the `kubectl create secret` command: + +``` +kubectl create secret generic secret-one --from-literal=key1=value1 +kubectl create secret generic secret-two --from-literal=key2=value2 +``` + +Each secret can contain multiple key-value pairs, and you can add more secrets as needed. + +# Configuring the Pod + +Next, define the pod configuration to mount these secrets into a single directory. Here’s an example configuration: + +``` +apiVersion: v1 +kind: Pod +metadata: + name: mypod +spec: + containers: + - name: mycontainer + image: myimage + volumeMounts: + - name: secret-volume1 + mountPath: "/etc/secrets/secret-one" + subPath: key1 + - name: secret-volume2 + mountPath: "/etc/secrets/secret-two" + subPath: key2 + volumes: + - name: secret-volume1 + secret: + secretName: secret-one + - name: secret-volume2 + secret: + secretName: secret-two +``` + +# Detailed Explanation + +- Volume Mounts: The `volumeMounts` section specifies where the secrets will be mounted within the container's file system. By using the `subPath` property, you can place each secret's content into a specific file within the target directory. +- Volumes: The volumes section links each volume to a Kubernetes secret. This ensures that the secrets are available to the container at runtime. + +In this example, secret-one and secret-two are mounted into `/etc/secrets/secret-one` and `/etc/secrets/secret-two`, respectively. The `subPath` ensures that each key-value pair from the secrets is mapped to a separate file within the specified directory. + +# Conclusion + +By mounting secrets into subdirectories using the `subPath` property, you can effectively manage multiple secrets within a single directory. This method enhances organization and accessibility, making it easier to handle secrets in your Kubernetes applications. diff --git a/content/posts/2024-09-04-azure-container-registry-403.md b/content/posts/2024-09-04-azure-container-registry-403.md new file mode 100644 index 00000000..02ebec7b --- /dev/null +++ b/content/posts/2024-09-04-azure-container-registry-403.md @@ -0,0 +1,22 @@ +--- +title: 'Mounting Multiple Kubernetes Secrets into One Directory' +author: Ryan +date: '2024-06-29' +layout: post +draft: true +categories: + - Kubernetes +tags: + - devops + - web development + - software development +--- + +# Introduction + +``` + +``` + +[![](https://rnemeth90.github.io/images/acr-403.png)](https://rnemeth90.github.io/images/acr-403.png) +[![](https://rnemeth90.github.io/images/acr-403-02.png)](https://rnemeth90.github.io/images/acr-403-02.png) diff --git a/content/posts/2024-12-05-dotnet-console-app-health-probe.md b/content/posts/2024-12-05-dotnet-console-app-health-probe.md new file mode 100644 index 00000000..e2694a1e --- /dev/null +++ b/content/posts/2024-12-05-dotnet-console-app-health-probe.md @@ -0,0 +1,106 @@ +--- +title: 'Kubernetes Health Probing in Dotnet Console Apps' +author: Ryan +date: '2024-12-05' +layout: post +draft: false +categories: + - Kubernetes +tags: + - devops + - software development + - dotnet + - sre +--- + +# Introduction + +This post covers a simple and efficient solution for implementing liveness probes in pods running console applications (think background services or utility DaemonSets). A common question I see in Kubernetes forums is: + + “How do I use health probes with console apps?” + +The typical responses often suggest: + +1. Sidecar Container with HTTP Server: Requires coding the server, building a sidecar container, and managing additional infrastructure. While effective, this can be overkill for lightweight applications. +2. Exec Probes with Shell Scripts: Feels hacky and can waste resources, depending on what the script does. + +Pods are meant to be lightweight, and both solutions can deviate from that principle. + +Instead, we’ll use a simple TCP listener to create an efficient liveness probe. Here’s the code: + +``` +using System; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Threading; + +class Program +{ + static void Main(string[] args) + { + int port = 666; // You can run this on a different port if necessary + + Thread tcpServerThread = new Thread(() => StartTcpServer(port)); + tcpServerThread.IsBackground = true; + tcpServerThread.Start(); + + Console.WriteLine("Application is running..."); + while (true) + { + // do some work + Thread.Sleep(1000); + } + } + + static void StartTcpServer(int port) + { + TcpListener server = null; + + try + { + server = new TcpListener(IPAddress.Any, port); + server.Start(); + Console.WriteLine($"Liveness server started on port {port}."); + + while (true) + { + TcpClient client = server.AcceptTcpClient(); + NetworkStream stream = client.GetStream(); + + byte[] buffer = new byte[256]; + int bytesRead = stream.Read(buffer, 0, buffer.Length); + string request = Encoding.ASCII.GetString(buffer, 0, bytesRead).Trim(); + + if (request.Equals("ping", StringComparison.OrdinalIgnoreCase)) + { + byte[] response = Encoding.ASCII.GetBytes("pong\n"); + stream.Write(response, 0, response.Length); + } + + client.Close(); + } + } + catch (Exception ex) + { + Console.WriteLine($"Error in liveness server: {ex.Message}"); + } + finally + { + server?.Stop(); + } + } +} +``` + +The StartTcpServer() method starts a simple TCP server in a thread running concurrent to the main thread. Use a `tcpSocket` liveness probe in your Kubernetes manifest. Kubernetes will then attempt to establish a TCP connection at configured intervals. You can test it by doing the same, or using a tool like `netcat`: + +``` +echo "ping" | nc localhost 666 +``` + +'pong' should be returned. + +Simply add this TCP server to your application and then configure the liveness probe. Examples can be found in the Kubernetes docs linked below. + +https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ diff --git a/public/404.html b/public/404.html index 37a698d1..c6e7f65b 100644 --- a/public/404.html +++ b/public/404.html @@ -1,337 +1,110 @@ - + + - -
- - - - - - - -