diff --git a/docs/releases.md b/docs/releases.md
index 533909ec..708e28dc 100644
--- a/docs/releases.md
+++ b/docs/releases.md
@@ -7,6 +7,7 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
 **Bug fixes + maintenance:**
 
 * Remove health check from `Dockerfile` and [document it](config.md#health-checks) ([#635](https://github.com/binwiederhier/ntfy/issues/635), thanks to [@Andersbiha](https://github.com/Andersbiha)) 
+* Fix panic when using Firebase without users ([#641](https://github.com/binwiederhier/ntfy/issues/641), thanks to [u/heavybell](https://www.reddit.com/user/heavybell/) for reporting)
 * Upgrade dialog: Disable submit button for free tier (no ticket)
 * Allow multiple `log-level-overrides` on the same field (no ticket)
 
diff --git a/server/server.go b/server/server.go
index 68cc4625..c849c56d 100644
--- a/server/server.go
+++ b/server/server.go
@@ -162,7 +162,13 @@ func New(conf *Config) (*Server, error) {
 		if err != nil {
 			return nil, err
 		}
-		firebaseClient = newFirebaseClient(sender, userManager)
+		// This awkward logic is required because Go is weird about nil types and interfaces.
+		// See issue #641, and https://go.dev/play/p/uur1flrv1t3 for an example
+		var auther user.Auther
+		if userManager != nil {
+			auther = userManager
+		}
+		firebaseClient = newFirebaseClient(sender, auther)
 	}
 	s := &Server{
 		config:         conf,
diff --git a/server/server_test.go b/server/server_test.go
index 381a5535..ccda967a 100644
--- a/server/server_test.go
+++ b/server/server_test.go
@@ -83,6 +83,32 @@ func TestServer_PublishWithFirebase(t *testing.T) {
 	require.Equal(t, "my first message", sender.Messages()[0].APNS.Payload.CustomData["message"])
 }
 
+func TestServer_PublishWithFirebase_WithoutUsers_AndWithoutPanic(t *testing.T) {
+	// This tests issue #641, which used to panic before the fix
+
+	firebaseKeyFile := filepath.Join(t.TempDir(), "firebase.json")
+	contents := `{
+  "type": "service_account",
+  "project_id": "ntfy-test",
+  "private_key_id": "fsfhskjdfhskdhfskdjfhsdf",
+  "private_key": "lalala",
+  "client_email": "firebase-adminsdk-muv04@ntfy-test.iam.gserviceaccount.com",
+  "client_id": "123123213",
+  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
+  "token_uri": "https://oauth2.googleapis.com/token",
+  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
+  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-muv04%40ntfy-test.iam.gserviceaccount.com"
+}
+`
+	require.Nil(t, os.WriteFile(firebaseKeyFile, []byte(contents), 0600))
+	c := newTestConfig(t)
+	c.FirebaseKeyFile = firebaseKeyFile
+	s := newTestServer(t, c)
+
+	response := request(t, s, "PUT", "/mytopic", "my first message", nil)
+	require.Equal(t, "my first message", toMessage(t, response.Body.String()).Message)
+}
+
 func TestServer_SubscribeOpenAndKeepalive(t *testing.T) {
 	t.Parallel()
 	c := newTestConfig(t)