Index: src/routes/activitypub.js
===================================================================
--- src/routes/activitypub.js	(revision 67fe57657c7618afe238798650ff114c6dc5c7c7)
+++ src/routes/activitypub.js	(revision 283f618f8d224646dfaad3dc3b04b9ac7c092b92)
@@ -17,6 +17,11 @@
 import AP from '../services/ActivityPubService.js';
 import { apReadLimiter, apInboxLimiter } from '../middleware/rate-limit.js';
+import { apEnabled } from '../services/SettingsService.js';
 
 const router = express.Router();
+// The whole fediverse layer can be turned off (solo "no federation" mode):
+// then /ap/*, WebFinger and NodeInfo are simply gone — the site is undiscoverable
+// and unfederatable.
+router.use((req, res, next) => { if (!apEnabled()) return res.status(404).end(); next(); });
 // Generous per-IP baseline over all /ap/* (reads). The inbox POST gets an
 // additional, tighter cap inline (it triggers outbound fetches).
Index: src/routes/admin-settings.js
===================================================================
--- src/routes/admin-settings.js	(revision 67fe57657c7618afe238798650ff114c6dc5c7c7)
+++ src/routes/admin-settings.js	(revision 283f618f8d224646dfaad3dc3b04b9ac7c092b92)
@@ -82,4 +82,5 @@
     smtp: mailerStatus(),
     footerNewsletter: getSetting('footer_newsletter') === '1',
+    apEnabledSetting: getSetting('ap_enabled', '1') !== '0',
     success: req.query.success || null,
     error: req.query.error || null,
@@ -166,4 +167,10 @@
 });
 
+// Fediverse (ActivityPub) on/off. Off = no federation + no fediverse reactions.
+router.post('/ap', requireGod, (req, res) => {
+  setSetting('ap_enabled', req.body.ap_enabled ? '1' : '0');
+  res.redirect('/admin/settings?success=' + encodeURIComponent('Fediverse-instelling opgeslagen'));
+});
+
 // Send a test email to a specified address (or the logged-in user).
 router.post('/smtp/test', requireGod, async (req, res) => {
