diff --git a/app/Controllers/Admin/PodcastController.php b/app/Controllers/Admin/PodcastController.php
index 0fe70a48bbe3d91c67cecaf1619d8f9ac1695d10..5583213b96b691c2c85b97849ae8fc3d17714472 100644
--- a/app/Controllers/Admin/PodcastController.php
+++ b/app/Controllers/Admin/PodcastController.php
@@ -192,6 +192,7 @@ class PodcastController extends BaseController
         }
 
         $podcast = new Podcast([
+            'guid' => podcast_uuid(url_to('podcast_feed', $this->request->getPost('name'))),
             'title' => $this->request->getPost('title'),
             'name' => $this->request->getPost('name'),
             'description_markdown' => $this->request->getPost('description'),
diff --git a/app/Controllers/Admin/PodcastImportController.php b/app/Controllers/Admin/PodcastImportController.php
index fbc0cca288ae9b10708aad04341145345b313d2b..2125d0972df22b0e7016f4fab868301fbc4ceaaa 100644
--- a/app/Controllers/Admin/PodcastImportController.php
+++ b/app/Controllers/Admin/PodcastImportController.php
@@ -128,11 +128,17 @@ class PodcastImportController extends BaseController
                     (string) $nsPodcast->location->attributes()['osm'],
                 );
             }
+            if (property_exists($nsPodcast, 'guid') && $nsPodcast->guid !== null) {
+                $guid = (string) $nsPodcast->guid;
+            } else {
+                $guid = podcast_uuid(url_to('podcast_feed', $this->request->getPost('name')));
+            }
 
             $podcast = new Podcast([
+                'guid' => $guid,
                 'name' => $this->request->getPost('name'),
                 'imported_feed_url' => $this->request->getPost('imported_feed_url'),
-                'new_feed_url' => base_url(route_to('podcast_feed', $this->request->getPost('name'))),
+                'new_feed_url' => url_to('podcast_feed', $this->request->getPost('name')),
                 'title' => (string) $feed->channel[0]->title,
                 'description_markdown' => $converter->convert($channelDescriptionHtml),
                 'description_html' => $channelDescriptionHtml,
diff --git a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
index b04c92667a82de5f1baddf01b4e7a7bbb3e36681..f330d0841c8fbdb2a655c3312c7997848501a68d 100644
--- a/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
+++ b/app/Database/Migrations/2020-05-30-101500_add_podcasts.php
@@ -24,6 +24,10 @@ class AddPodcasts extends Migration
                 'unsigned' => true,
                 'auto_increment' => true,
             ],
+            'guid' => [
+                'type' => 'CHAR',
+                'constraint' => 36,
+            ],
             'actor_id' => [
                 'type' => 'INT',
                 'unsigned' => true,
@@ -190,6 +194,7 @@ class AddPodcasts extends Migration
         $this->forge->addPrimaryKey('id');
         // TODO: remove name in favor of username from actor
         $this->forge->addUniqueKey('name');
+        $this->forge->addUniqueKey('guid');
         $this->forge->addUniqueKey('actor_id');
         $this->forge->addForeignKey('actor_id', 'activitypub_actors', 'id', '', 'CASCADE');
         $this->forge->addForeignKey('category_id', 'categories', 'id');
diff --git a/app/Entities/Podcast.php b/app/Entities/Podcast.php
index 20dd2840890ec9939e3d17ff404ecf9c87dc972c..6ed3b702a1c9aa5b53e6ffecee6891840bd25e1d 100644
--- a/app/Entities/Podcast.php
+++ b/app/Entities/Podcast.php
@@ -23,6 +23,7 @@ use RuntimeException;
 
 /**
  * @property int $id
+ * @property string $guid
  * @property int $actor_id
  * @property Actor|null $actor
  * @property string $name
@@ -137,6 +138,7 @@ class Podcast extends Entity
      */
     protected $casts = [
         'id' => 'integer',
+        'guid' => 'string',
         'actor_id' => 'integer',
         'name' => 'string',
         'title' => 'string',
diff --git a/app/Helpers/misc_helper.php b/app/Helpers/misc_helper.php
index 68404ba10418f5fd32e253ca4866fdf6dab12de1..212b8271ee331fbc8cd532d52e763dd371fbb9f6 100644
--- a/app/Helpers/misc_helper.php
+++ b/app/Helpers/misc_helper.php
@@ -148,4 +148,18 @@ if (! function_exists('format_duration')) {
     }
 }
 
+if (! function_exists('podcast_uuid')) {
+    /**
+     * Generate UUIDv5 for podcast. For more information, see
+     * https://github.com/Podcastindex-org/podcast-namespace/blob/main/docs/1.0.md#guid
+     */
+    function podcast_uuid(string $feedUrl): string
+    {
+        $uuid = service('uuid');
+        // 'ead4c236-bf58-58c6-a2c6-a6b28d128cb6' is the uuid of the podcast namespace
+        return $uuid->uuid5('ead4c236-bf58-58c6-a2c6-a6b28d128cb6', $feedUrl)
+            ->toString();
+    }
+}
+
 //--------------------------------------------------------------------
diff --git a/app/Helpers/rss_helper.php b/app/Helpers/rss_helper.php
index eeb24254da1a78cd5396439e84d26a2155e4221e..10079326600cc84e1de5e65a55c098b58e996f33 100644
--- a/app/Helpers/rss_helper.php
+++ b/app/Helpers/rss_helper.php
@@ -50,6 +50,7 @@ if (! function_exists('get_rss_feed')) {
         $channel->addChild('generator', 'Castopod Host - https://castopod.org/');
         $channel->addChild('docs', 'https://cyber.harvard.edu/rss/rss.html');
 
+        $channel->addChild('guid', $podcast->guid, $podcastNamespace);
         $channel->addChild('title', $podcast->title);
         $channel->addChildWithCDATA('description', $podcast->description_html);
 
diff --git a/app/Models/PodcastModel.php b/app/Models/PodcastModel.php
index 1b20c1feecc2f79f3aed6eaebc262bd9cb145f10..739593e73af6405449fee6cbeaf92bea70ca3ddf 100644
--- a/app/Models/PodcastModel.php
+++ b/app/Models/PodcastModel.php
@@ -33,6 +33,7 @@ class PodcastModel extends Model
      */
     protected $allowedFields = [
         'id',
+        'guid',
         'title',
         'name',
         'description_markdown',