diff --git a/dev.variables.sh b/dev.variables.sh
index afa09c2bf730f8d19ed2bdb8ab1791df9d5e7a9e..c679357063c1fa52e922f40614ce685db6b65061 100644
--- a/dev.variables.sh
+++ b/dev.variables.sh
@@ -1,5 +1,5 @@
 SCHEDULE="0 8 * * *"
 DB_MOUNTPOINT="/mnt/data2/test/package_alerts"
 INTERESTING_PACKAGES="dev.packages.yml"
-FEEDS="rhel-8-for-x86_64-baseos-rpms,rhel-8-for-x86_64-appstream-rpms,rhel-9-for-x86_64-baseos-rpms,rhel-9-for-x86_64-appstream-rpms"
+FEEDS="rhel-8-for-x86_64-baseos-rpms,rhel-8-for-x86_64-appstream-rpms,rhel-9-for-x86_64-baseos-rpms,rhel-9-for-x86_64-appstream-rpms,almalinux-8-for-x86_64-AppStream-rpms,almalinux-8-for-x86_64-BaseOS-rpms,almalinux-9-for-x86_64-AppStream-rpms,almalinux-9-for-x86_64-BaseOS-rpms"
 MATTERMOST_INTEGRATION_URL="https://mattermost.web.cern.ch/hooks/cy45ecb3kpgwbm88smkn4fa43h"
diff --git a/package_alerts/dev.packages.yml b/package_alerts/dev.packages.yml
index f1d9b2a8c7effdef8e470256c16b725ad4e17d19..7a14b517365c591e868f4850d812d96c8f098c6c 100644
--- a/package_alerts/dev.packages.yml
+++ b/package_alerts/dev.packages.yml
@@ -6,6 +6,9 @@
 # and no notes will be included in the MM message.
 ---
 packages:
+  almalinux-release:
+    notes: |-
+      **MANUAL ACTION REQUIRED**: This is a "dangerous package" and it will need to be [rebuilt by hand](https://linuxops.web.cern.ch/distributions/snapshots/#-release-packages-the-dangerous-rpms). If you don't do it **today**, the daily snapshot will stop tomorrow and you'll have more work to do then.
   redhat-release:
     notes: |-
       **MANUAL ACTION REQUIRED**: This is a "dangerous package" and it will need to be [rebuilt by hand](https://linuxops.web.cern.ch/distributions/snapshots/#-release-packages-the-dangerous-rpms). If you don't do it **today**, the daily snapshot will stop tomorrow and you'll have more work to do then.
diff --git a/package_alerts/package_alerts b/package_alerts/package_alerts
index afb3287d4e00e57875ff71a9c8fe1c7f968f1bbf..043c32d4800d79c7f31b61c71589abe6da877f36 100755
--- a/package_alerts/package_alerts
+++ b/package_alerts/package_alerts
@@ -82,19 +82,23 @@ def do_execute(cmd, tdir="/tmp", return_output=False, return_error=False):
     return True
 
 
-def get_changelog(token, checksum):
+def get_changelog(token, payload):
     """get the changelog for a rpm, which requires downloading it"""
+    # Almalinux
+    if token is None:
+        url = payload
+    else:
+        url = f"https://api.access.redhat.com/management/v1/packages/{payload}/download"
     # We don't usually retry stuff from api calls as the script runs
     # frequently, however - in this case a failure results in a blank
     # changelog which is not very useful
     attempts = 0
     max_attempts = 3
     rpm_downloaded = False
-    temp_file = generate_temp_file("checksum")
-    url = f"https://api.access.redhat.com/management/v1/packages/{checksum}/download"
+    temp_file = generate_temp_file("payload")
     while attempts < max_attempts:
         attempts += 1
-        result = call_api(token, url, stream=True)
+        result = request_url(token, url, stream=True)
         if result.status_code == 200:
             # TODO: try and do this with dnf 'add_remote_rpms', although we would need to auth
             with open(temp_file, "wb") as f:
@@ -143,26 +147,49 @@ def get_token(ot):
     return token
 
 
-def call_api(token, url, params=None, stream=False):
-    """call the api with a token"""
-    headers = {"Authorization": f"Bearer {token}"}
+def request_url(token, url, params=None, stream=False):
+    """Make a request to a url, with an optional token"""
+    if token is None:
+        headers = {}
+    else:
+        headers = {"Authorization": f"Bearer {token}"}
     result = requests.get(url, headers=headers, params=params, stream=stream)
     return result
 
 
 def get_upstream(token, feed):
-    """retrieve full list of packages from a cset"""
-    arch = re.match(r"(\w+-[0-9]-\w+-)(\w+)(-\w+-\w+)", feed).group(2)
+    """retrieve full list of packages from a cset / package url"""
+    packages = []
+    matches = re.match(f"(\w+)-([0-9])-\w+-(\w+)-(\w+)", feed)
+    arch = matches.group(3)
+    # almalinux is simplier, so we process it earlier
+    if 'almalinux' in feed:
+        release = matches.group(2)
+        repo = matches.group(4)
+        base = dnf.Base()
+        conf = base.conf
+        base.repos.add_new_repo('package_alerts', conf,
+        baseurl=[f"https://repo.almalinux.org/almalinux/{release}/{repo}/{arch}/os/"])
+        base.fill_sack(load_system_repo=False)
+        q = base.sack.query()
+        i = q.available()
+        i = i.filter(arch=[arch, 'noarch'])
+        upstream = list(i)
+        for pkg in upstream:
+            # We use the url later in get_changelog
+            url=f"https://repo.almalinux.org/almalinux/{release}/{repo}/{arch}/os/Packages/{pkg}.rpm"
+            packages.append(f"{str(pkg).rsplit('.',1)[0]},{url}")
+        return packages
+    # From here, we are working solely on RHEL API stuff
     url = (
         f"https://api.access.redhat.com/management/v1/packages/cset/{feed}/arch/{arch}"
     )
     offset = 0
-    packages = []
     while True:
         signal.signal(signal.SIGALRM, timeout_handler)
         signal.alarm(30)
         try:
-            result = call_api(token, url, params={"limit": 100, "offset": offset})
+            result = request_url(token, url, params={"limit": 100, "offset": offset})
         except TimeoutError:
             print(f"Timeout occurred whilst trying to process {feed} with offset {offset}")
             continue
@@ -176,10 +203,10 @@ def get_upstream(token, feed):
         count = j["pagination"]["count"]
         for p in j["body"]:
             package = f"{p['name']}-{p['version']}-{p['release']}"
-            checksum = p["checksum"]
+            payload = p["checksum"]
             package_arch = p["arch"]
             if package_arch == arch:
-                packages.append(f"{package},{checksum}")
+                packages.append(f"{package},{payload}")
         if count == 100:
             offset += count
             print(f"{feed}: incrementing offset to {offset}", flush=True)
@@ -212,7 +239,7 @@ def set_local(packages, feed):
 def format_release(p, f, token):
     """format message and send payload to mattermost"""
     newpackage = p.split(',')[0]
-    checksum = p.split(',')[1]
+    payload = p.split(',')[1]
     logfile.write(f"{newpackage}\n")
     # check for epoch in name, and if it exists: ignore it
     try:
@@ -240,7 +267,7 @@ def format_release(p, f, token):
         except (TypeError, KeyError):
             notes = None
 
-        cl = get_changelog(token, checksum)
+        cl = get_changelog(token, payload)
         values = {}
         # Using Mattermost attachments for prettier messages
         # https://developers.mattermost.com/integrate/admin-guide/admin-message-attachments/
@@ -274,7 +301,10 @@ def timeout_handler(num, stack):
 if __name__ == "__main__":
     """this is the main class, it's amazing."""
     for feed in feeds:
-        token = get_token(offline_token)
+        if 'rhel' in feed:
+            token = get_token(offline_token)
+        else:
+            token = None
         print(f"working on feed {feed}", flush=True)
         local_packages = get_local(feed)
         upstream_packages = get_upstream(token, feed)
diff --git a/package_alerts/prod.packages.yml b/package_alerts/prod.packages.yml
index a1155ae50b724c1a45ee89f44947e7e181a3f90a..1996704de67995e36410c26c564b395ce38426e0 100644
--- a/package_alerts/prod.packages.yml
+++ b/package_alerts/prod.packages.yml
@@ -6,6 +6,9 @@
 # and no notes will be included in the MM message.
 ---
 packages:
+  almalinux-release:
+    notes: |-
+      **MANUAL ACTION REQUIRED**: This is a "dangerous package" and it will need to be [rebuilt by hand](https://linuxops.web.cern.ch/distributions/snapshots/#-release-packages-the-dangerous-rpms). If you don't do it **today**, the daily snapshot will stop tomorrow and you'll have more work to do then.
   redhat-release:
     notes: |-
       **MANUAL ACTION REQUIRED**: This is a "dangerous package" and it will need to be [rebuilt by hand](https://linuxops.web.cern.ch/distributions/snapshots/#-release-packages-the-dangerous-rpms). If you don't do it **today**, the daily snapshot will stop tomorrow and you'll have more work to do then.
diff --git a/prod.variables.sh b/prod.variables.sh
index 8da745f0dfffacbf118c3159003fb6ec99d92937..10233ef52f672c47e415ee161789e56af219a8df 100644
--- a/prod.variables.sh
+++ b/prod.variables.sh
@@ -1,5 +1,5 @@
 SCHEDULE="*/30 * * * *"
 DB_MOUNTPOINT="/mnt/data2/package_alerts"
 INTERESTING_PACKAGES="prod.packages.yml"
-FEEDS="rhel-8-for-x86_64-baseos-rpms,rhel-8-for-x86_64-appstream-rpms,rhel-9-for-x86_64-baseos-rpms,rhel-9-for-x86_64-appstream-rpms"
+FEEDS="rhel-8-for-x86_64-baseos-rpms,rhel-8-for-x86_64-appstream-rpms,rhel-9-for-x86_64-baseos-rpms,rhel-9-for-x86_64-appstream-rpms,almalinux-8-for-x86_64-AppStream-rpms,almalinux-8-for-x86_64-BaseOS-rpms,almalinux-9-for-x86_64-AppStream-rpms,almalinux-9-for-x86_64-BaseOS-rpms"
 MATTERMOST_INTEGRATION_URL="https://mattermost.web.cern.ch/hooks/qiodnmzwbjg9zkyxkxoh1h47sh"