diff --git a/doc/how_to/profiling/admin.md b/doc/how_to/profiling/admin.md
index 5f47c39246..193f29f911 100644
--- a/doc/how_to/profiling/admin.md
+++ b/doc/how_to/profiling/admin.md
@@ -6,8 +6,22 @@ This guide addresses how to enable the admin Panel to begin monitoring resource
The `/admin` panel provides an overview of the current application and provides tools for debugging and profiling. It can be enabled by passing the ``--admin`` argument to the `panel serve` command.
+```bash
+panel serve my-app.py --admin
+```
+
When you have successfully enabled it you should be able to visit the `/admin` endpoint of your application, e.g. if you are serving locally on port 5006, visit `http://localhost:5006/admin`. You should now be greeted with the overview page, which provides some details about currently active sessions, running versions and resource usage (if `psutil` is installed):
+## Changing the admin panel endpoint
+
+You can change the endpoint that the admin page is rendered at by using the flag `--admin-endpoint="/my-new-admin-endpoint"`. This will change where the admin endpoint is in the Bokeh server, and cause a `404: Not Found` page to be shown if you navigate to the default `/admin` path discussed above. As an example, using the following command to start your Panel app
+
+```bash
+panel serve my-app.py --admin --admin-endpoint="/my-new-admin-endpoint"
+```
+
+and navigating to [http://localhost:5006/admin](http://localhost:5006/admin) will result in a 404 page, however, navigating to [http://localhost:5006/my-new-admin-endpoint](http://localhost:5006/my-new-admin-endpoint) will result in the admin panel.
+
## Related Resources
diff --git a/panel/command/serve.py b/panel/command/serve.py
index 08c19af345..53fa9fc16b 100644
--- a/panel/command/serve.py
+++ b/panel/command/serve.py
@@ -182,6 +182,12 @@ class Serve(_BkServe):
action = 'store_true',
help = "Whether to add an admin panel."
)),
+ ('--admin-endpoint', dict(
+ action = 'store',
+ type = str,
+ help = "Name to use for the admin endpoint.",
+ default = None
+ )),
('--admin-log-level', dict(
action = 'store',
default = None,
@@ -348,17 +354,24 @@ def customize_kwargs(self, args, server_kwargs):
if args.admin:
from ..io.admin import admin_panel
from ..io.server import per_app_patterns
+
+ # If `--admin-endpoint` is not set, then we default to the `/admin` path.
+ admin_path = "/admin"
+ if args.admin_endpoint:
+ admin_path = args.admin_endpoint
+ admin_path = admin_path if admin_path.startswith('/') else f'/{admin_path}'
+
config._admin = True
app = Application(FunctionHandler(admin_panel))
unused_timeout = args.check_unused_sessions or 15000
state._admin_context = app_ctx = AdminApplicationContext(
- app, unused_timeout=unused_timeout, url='/admin'
+ app, unused_timeout=unused_timeout, url=admin_path
)
if all(not isinstance(handler, DocumentLifecycleHandler) for handler in app._handlers):
app.add(DocumentLifecycleHandler())
app_patterns = []
for p in per_app_patterns:
- route = '/admin' + p[0]
+ route = admin_path + p[0]
context = {"application_context": app_ctx}
app_patterns.append((route, p[1], context))
diff --git a/panel/config.py b/panel/config.py
index 0e13c349c1..c8e9f94a12 100644
--- a/panel/config.py
+++ b/panel/config.py
@@ -218,6 +218,8 @@ class _config(_base_config):
_admin = param.Boolean(default=False, doc="Whether the admin panel was enabled.")
+ _admin_endpoint = param.String(default=None, doc="Name to use for the admin endpoint.")
+
_admin_log_level = param.Selector(
default='DEBUG', objects=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'],
doc="Log level of the Admin Panel logger")
@@ -455,6 +457,10 @@ def _template_hook(self, value):
def _doc_build(self):
return os.environ.get('PANEL_DOC_BUILD')
+ @property
+ def admin_endpoint(self):
+ return os.environ.get('PANEL_ADMIN_ENDPOINT', self._admin_endpoint)
+
@property
def admin_log_level(self):
admin_log_level = os.environ.get('PANEL_ADMIN_LOG_LEVEL', self._admin_log_level)
@@ -580,7 +586,6 @@ def theme(self):
config = _config(**{k: None if p.allow_None else getattr(_config, k)
for k, p in _params.items() if k != 'name'})
-
class panel_extension(_pyviz_extension):
"""
Initializes and configures Panel. You should always run `pn.extension`.
diff --git a/panel/tests/command/test_serve.py b/panel/tests/command/test_serve.py
index d4248da817..33099f5d58 100644
--- a/panel/tests/command/test_serve.py
+++ b/panel/tests/command/test_serve.py
@@ -29,6 +29,30 @@ def test_autoreload_app(py_file):
assert r2.status_code == 200
assert "