diff --git a/.gitignore b/.gitignore
index 1806fcf..54d8057 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,4 +7,9 @@
 /config.yml
 /transcripts
 /Linux-x64
-/Windows-x64
\ No newline at end of file
+/Windows-x64
+
+Folder.DotSettings.user
+
+packaging/rpmbuild-nightly/
+packaging/rpmbuild/
\ No newline at end of file
diff --git a/Jenkinsfile b/Jenkinsfile
index 70d3161..50d05e6 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -1,41 +1,95 @@
-pipeline {
+pipeline
+{
   agent any
-  stages {
-    stage('Setup Dependencies') {
-      steps {
+  stages
+  {
+    stage('Setup Dependencies')
+    {
+      steps
+      {
         sh 'dotnet restore'
       }
     }
-    stage('Build') {
-      parallel {
-        stage('Linux') {
-          steps {
-            sh 'dotnet publish -r linux-x64 -c Release -p:PublishTrimmed=true --self-contained true --no-restore --output Linux-x64/'
-            sh 'mv Linux-x64/SupportChild Linux-x64/SupportChild-SC'
-            sh 'dotnet publish -r linux-x64 -c Release --self-contained false --no-restore --output Linux-x64/'
+    stage('Build')
+    {
+      parallel
+      {
+        stage('Linux')
+        {
+          steps
+          {
+            sh 'dotnet publish -r linux-x64 -c Release -p:PublishTrimmed=true --self-contained true --no-restore --output linux-x64/'
+            sh 'mv linux-x64/supportchild linux-x64/supportchild-sc'
+            sh 'dotnet publish -r linux-x64 -c Release --self-contained false --no-restore --output linux-x64/'
+            archiveArtifacts(artifacts: 'linux-x64/supportchild', caseSensitive: true)
+            archiveArtifacts(artifacts: 'linux-x64/supportchild-sc', caseSensitive: true)
           }
         }
-        stage('Windows') {
-          steps {
-            sh 'dotnet publish -r win-x64 -c Release -p:PublishTrimmed=true --self-contained true --no-restore --output Windows-x64/'
-            sh 'mv Windows-x64/SupportChild.exe Windows-x64/SupportChild-SC.exe'
-            sh 'dotnet publish -r win-x64 -c Release --self-contained false --no-restore --output Windows-x64/'
+        stage('Windows')
+        {
+          steps
+          {
+            sh 'dotnet publish -r win-x64 -c Release -p:PublishTrimmed=true --self-contained true --no-restore --output windows-x64/'
+            sh 'mv windows-x64/supportchild.exe windows-x64/supportchild-sc.exe'
+            sh 'dotnet publish -r win-x64 -c Release --self-contained false --no-restore --output windows-x64/'
+            archiveArtifacts(artifacts: 'windows-x64/supportchild.exe', caseSensitive: true)
+            archiveArtifacts(artifacts: 'windows-x64/supportchild-sc.exe', caseSensitive: true)
           }
         }
-      }
-    }
-    stage('Archive') {
-      parallel {
-        stage('Linux') {
-          steps {
-            archiveArtifacts(artifacts: 'Linux-x64/SupportChild', caseSensitive: true)
-            archiveArtifacts(artifacts: 'Linux-x64/SupportChild-SC', caseSensitive: true)
+        stage('RHEL9')
+        {
+          agent
+          {
+            dockerfile
+            {
+              filename 'packaging/RHEL9.Dockerfile'
+            }
+          }
+          environment
+          {
+            DOTNET_CLI_HOME = "/tmp/.dotnet"
+          }
+          when
+          {
+            expression
+            {
+              return env.BRANCH_NAME == 'main' || env.BRANCH_NAME == 'beta' || env.BRANCH_NAME == 'jenkins-testing';
+            }
+          }
+          steps
+          {
+            sh 'rpmbuild -bb packaging/supportchild-nightly.spec --define "_topdir $PWD/.rpmbuild-el9"'
+            sh 'mkdir linux-x64'
+            sh 'cp .rpmbuild-el9/RPMS/x86_64/supportchild-nightly-*.el9.x86_64.rpm linux-x64/'
+            archiveArtifacts(artifacts: 'linux-x64/supportchild-nightly-*.el9.x86_64.rpm', caseSensitive: true)
           }
         }
-        stage('Windows') {
-          steps {
-            archiveArtifacts(artifacts: 'Windows-x64/SupportChild.exe', caseSensitive: true)
-            archiveArtifacts(artifacts: 'Windows-x64/SupportChild-SC.exe', caseSensitive: true)
+        stage('RHEL8')
+        {
+          agent
+          {
+            dockerfile
+            {
+              filename 'packaging/RHEL8.Dockerfile'
+            }
+          }
+          environment
+          {
+            DOTNET_CLI_HOME = "/tmp/.dotnet"
+          }
+          when
+          {
+            expression
+            {
+              return env.BRANCH_NAME == 'main' || env.BRANCH_NAME == 'beta' || env.BRANCH_NAME == 'jenkins-testing';
+            }
+          }
+          steps
+          {
+            sh 'rpmbuild -bb packaging/supportchild-nightly.spec --define "_topdir $PWD/.rpmbuild-el8"'
+            sh 'mkdir linux-x64'
+            sh 'cp .rpmbuild-el8/RPMS/x86_64/supportchild-nightly-*.el8.x86_64.rpm linux-x64/'
+            archiveArtifacts(artifacts: 'linux-x64/supportchild-nightly-*.el8.x86_64.rpm', caseSensitive: true)
           }
         }
       }
diff --git a/SupportChild.csproj b/SupportChild.csproj
index 04b5ffd..879783b 100644
--- a/SupportChild.csproj
+++ b/SupportChild.csproj
@@ -5,6 +5,7 @@
       <Version>4.0.1</Version>
       <ApplicationIcon>ellie_icon.ico</ApplicationIcon>
       <TargetFramework>net9.0</TargetFramework>
+      <AssemblyName>supportchild</AssemblyName>
       <StartupObject>SupportChild.SupportChild</StartupObject>
       <RuntimeIdentifiers>win-x64;linux-x64</RuntimeIdentifiers>
       <PublishSingleFile>true</PublishSingleFile>
diff --git a/Utilities.cs b/Utilities.cs
index 71149dc..a1a5870 100644
--- a/Utilities.cs
+++ b/Utilities.cs
@@ -4,6 +4,7 @@ using System.Globalization;
 using System.IO;
 using System.Linq;
 using System.Reflection;
+using System.Text;
 using System.Threading.Tasks;
 using DSharpPlus.Entities;
 
@@ -102,7 +103,7 @@ public static class Utilities
             throw new InvalidOperationException("Could not load manifest resource stream.");
         }
 
-        using StreamReader reader = new StreamReader(stream);
+        using StreamReader reader = new StreamReader(stream, Encoding.Unicode);
         return reader.ReadToEnd();
     }
 
diff --git a/packaging/RHEL8.Dockerfile b/packaging/RHEL8.Dockerfile
new file mode 100644
index 0000000..01986ed
--- /dev/null
+++ b/packaging/RHEL8.Dockerfile
@@ -0,0 +1,2 @@
+FROM redhat/ubi8:latest
+RUN dnf install dotnet-sdk-9.0 rpm-build git -y
\ No newline at end of file
diff --git a/packaging/RHEL9.Dockerfile b/packaging/RHEL9.Dockerfile
new file mode 100644
index 0000000..060a29d
--- /dev/null
+++ b/packaging/RHEL9.Dockerfile
@@ -0,0 +1,2 @@
+FROM redhat/ubi9:latest
+RUN dnf install dotnet-sdk-9.0 rpm-build git -y
\ No newline at end of file
diff --git a/packaging/supportchild-nightly.spec b/packaging/supportchild-nightly.spec
new file mode 100644
index 0000000..b8c87f4
--- /dev/null
+++ b/packaging/supportchild-nightly.spec
@@ -0,0 +1,58 @@
+%global debug_package %{nil}
+%global repo_root %{_topdir}/..
+
+Summary:    A support ticket Discord bot
+Name:       supportchild-nightly
+Version:    %(sed -ne '/Version/{s/.*<Version>\(.*\)<\/Version>.*/\1/p;q;}' < SupportChild.csproj)
+Release:    %(date "+%%Y%%m%%d%%H%%M%%S")%{?dist}
+License:    GPLv3
+URL:        https://toastielab.dev/toastie-stuff/SupportChild
+Source:     https://toastielab.dev/toastie-stuff/SupportChild/archive/main.zip
+Packager:   Toastie_t0ast
+
+BuildRequires: systemd-rpm-macros
+Requires: dotnet-runtime-9.0
+%{?systemd_requires}
+
+%description
+A support ticket Discord bot. Uses a MySQL database for storage of ticket
+information. Creates formatted HTML ticket transcripts when tickets are closed.
+
+%prep
+%setup -T -c
+
+%build
+dotnet publish %{repo_root}/SupportChild.csproj -p:PublishSingleFile=true -r linux-x64 -c Release --self-contained false --output %{_builddir}/out
+
+%install
+%{__install} -d %{buildroot}/usr/bin
+%{__install} %{_builddir}/out/supportchild %{buildroot}/usr/bin/supportchild
+# rpmbuild post-processing using the strip command breaks dotnet binaries, remove the executable bit to avoid it
+chmod 644 %{buildroot}/usr/bin/supportchild
+
+%{__install} -d %{buildroot}/usr/lib/systemd/system
+%{__install} %{repo_root}/packaging/supportchild.service %{buildroot}/usr/lib/systemd/system/
+
+%{__install} -d %{buildroot}/etc/supportchild/
+%{__install} %{repo_root}/default_config.yml %{buildroot}/etc/supportchild/config.yml
+
+%pre
+getent group supportchild > /dev/null || groupadd supportchild
+getent passwd supportchild > /dev/null || useradd -r -s /sbin/nologin -g supportchild supportchild
+
+%post
+%systemd_post supportchild.service
+
+%preun
+%systemd_preun supportchild.service
+
+%postun
+%systemd_postun_with_restart supportchild.service
+if [[ "$1" == "0" ]]; then
+  getent passwd supportchild > /dev/null && userdel supportchild
+fi
+
+%files
+%attr(0755,root,root) /usr/bin/supportchild
+%attr(0644,root,root) /usr/lib/systemd/system/supportchild.service
+%config %attr(0600, supportchild, supportchild) /etc/supportchild/config.yml
\ No newline at end of file
diff --git a/packaging/supportchild.service b/packaging/supportchild.service
new file mode 100644
index 0000000..a981d80
--- /dev/null
+++ b/packaging/supportchild.service
@@ -0,0 +1,14 @@
+[Unit]
+Description=SupportChild Ticket Discord Bot
+Documentation=https://toastielab.dev/toastie-stuff/SupportChild
+After=network.target
+Wants=network.target
+
+[Service]
+User=supportchild
+ExecStart=/usr/bin/supportchild --config /etc/supportchild/config.yml
+Restart=no
+Type=exec
+
+[Install]
+WantedBy=multi-user.target
\ No newline at end of file
diff --git a/packaging/supportchild.spec b/packaging/supportchild.spec
new file mode 100644
index 0000000..6c60e91
--- /dev/null
+++ b/packaging/supportchild.spec
@@ -0,0 +1,58 @@
+%global debug_package %{nil}
+%global repo_root %{_topdir}/..
+
+Summary:    A support ticket Discord bot
+Name:       supportchild
+Version:    %(sed -ne '/Version/{s/.*<Version>\(.*\)<\/Version>.*/\1/p;q;}' < SupportChild.csproj)
+Release:    1%{?dist}
+License:    GPLv3
+URL:        https://toastielab.dev/toastie-stuff/SupportChild
+Source:     https://toastielab.dev/toastie-stuff/SupportChild/archive/main.zip
+Packager:   Toastie_t0ast
+
+BuildRequires: systemd-rpm-macros
+Requires: dotnet-runtime-9.0
+%{?systemd_requires}
+
+%description
+A support ticket Discord bot. Uses a MySQL database for storage of ticket
+information. Creates formatted HTML ticket transcripts when tickets are closed.
+
+%prep
+%setup -T -c
+
+%build
+dotnet publish %{repo_root}/SupportChild.csproj -p:PublishSingleFile=true -r linux-x64 -c Release --self-contained false --output %{_builddir}/out
+
+%install
+%{__install} -d %{buildroot}/usr/bin
+%{__install} %{_builddir}/out/supportchild %{buildroot}/usr/bin/supportchild
+# rpmbuild post-processing using the strip command breaks dotnet binaries, remove the executable bit to avoid it
+chmod 644 %{buildroot}/usr/bin/supportchild
+
+%{__install} -d %{buildroot}/usr/lib/systemd/system
+%{__install} %{repo_root}/packaging/supportchild.service %{buildroot}/usr/lib/systemd/system/
+
+%{__install} -d %{buildroot}/etc/supportchild/
+%{__install} %{repo_root}/default_config.yml %{buildroot}/etc/supportchild/config.yml
+
+%pre
+getent group supportchild > /dev/null || groupadd supportchild
+getent passwd supportchild > /dev/null || useradd -r -s /sbin/nologin -g supportchild supportchild
+
+%post
+%systemd_post supportchild.service
+
+%preun
+%systemd_preun supportchild.service
+
+%postun
+%systemd_postun_with_restart supportchild.service
+if [[ "$1" == "0" ]]; then
+  getent passwd supportchild > /dev/null && userdel supportchild
+fi
+
+%files
+%attr(0755,root,root) /usr/bin/supportchild
+%attr(0644,root,root) /usr/lib/systemd/system/supportchild.service
+%config %attr(0600, supportchild, supportchild) /etc/supportchild/config.yml
\ No newline at end of file