From 05cf168d35df622b51b710bfeaeaf0174631488c Mon Sep 17 00:00:00 2001 From: Shubham Naik Date: Tue, 10 Dec 2024 13:36:20 -0800 Subject: [PATCH] feat: support local https mode (#2217) Co-authored-by: Shubham Naik --- certs/README.md | 9 +++++++++ certs/localhost-key.pem | 28 ++++++++++++++++++++++++++++ certs/localhost.pem | 26 ++++++++++++++++++++++++++ letta/cli/cli.py | 1 + letta/server/rest_api/app.py | 25 ++++++++++++++++++------- 5 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 certs/README.md create mode 100644 certs/localhost-key.pem create mode 100644 certs/localhost.pem diff --git a/certs/README.md b/certs/README.md new file mode 100644 index 00000000..87f56da3 --- /dev/null +++ b/certs/README.md @@ -0,0 +1,9 @@ +# About +These certs are used to set up a localhost https connection to the ADE. + +## Instructions +1. Install [mkcert](https://github.com/FiloSottile/mkcert) +2. Run `mkcert -install` +3. Run letta with the environment variable `LOCAL_HTTPS=true` +4. Access the app at [https://app.letta.com/development-servers/local/dashboard](https://app.letta.com/development-servers/local/dashboard) +5. Click "Add remote server" and enter `https://localhost:8283` as the URL, leave password blank unless you have secured your ADE with a password. diff --git a/certs/localhost-key.pem b/certs/localhost-key.pem new file mode 100644 index 00000000..363a191f --- /dev/null +++ b/certs/localhost-key.pem @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDenaHTolfy9TzX +AUd60yPO1W0mpxdDTuxr2p3tBUaQJt5bEGzJbs1M0i5YVRK/SxtYZQvyqmI0ULKN +8+evKSEpJoDgLfFKM266jzKDSXd5XBQ3XuuxbKq6NV6qoTdweJ0zP0XXDUnKoTN6 +eMkUi8hD9P1TR3Ok3VGnT1wsdG0wPwRPDI/sD92GASL4ViUy/1Llrs7GjlOC+7M2 +GMoGifSHjmx2xgZ/K8cdD2q15iJJlhdbgCwfejcQlP7cmLtSJHH188EZeoFPEfNS +UpYNglS1kx0D/LC1ooTQRkCpLAnxeonMQZS5O5/q/zyxftkyKO+NInR6DtM0Uj8f +Gu5UDw1TAgMBAAECggEBANhqpkf4K0gm4V6j/7mISedp1RMenZ7xuyWfAqjJ2C+L +md8tuJSbAzsLmcKF8hPGEG9+zH685Xu2d99InpPKiFJY/DD0eP6JwbvcOl8nrN5u +hbjOrpNt8QvVlpKK6DqPB0Qq3tqSMIqs7D7D7bfrrGVkZmHvtJ0yC497t0AAb6XV +zTtnY9K6LVxb/t+eIDDX1AvE7i2WC+j1YgfexbM0VI/g4fveEVaKPFkWF3nSm0Ag +BmqzfGFUWKhBZmWpU0m86Zc45q575Bl64yXEQDYocUw3UfOp5/uF0lwuVe5Bpq/w +hIJgrW6RLzy20QFgPDxHhG3QdBpq4gB9BxCrMb+yhQECgYEA6jL1pD0drczxfaWC +bh+VsbVrRnz/0XDlPjaysO+qKsNP104gydeyyB6RcGnO8PssvFMCJNQlMhkEpp9x +bOwR36a4A2absC/osGgFH4pYyN2wqDb+qE2A3M+rnSGourd09y8BsCovN+5YsozK +HCnqjNWUweypU+RUvtM5jztsiOUCgYEA81ajdczpsysSn0xIFF0exvnnPLy/AiOR +uEFbPi0kavy7niwd609JFsSOwUXg2QavBNeoLH+YrQhueDoBJZANerLfLD8jqQxD +ojB6DkHwK5Vf9NIm8DZQ6trtf8xWGB/TuwpkWHm1wMdlCbmH38MukU4p6as7FKzT +8J57p/TfcdcCgYEAyDqfVzbFTBWfFbxOghZQ5mlj+RTfplHuPL2JEssk4oCvnzV1 +xPu8J2ozEDf2LIOiYLRbbd9OmcFX/5jr4aMHOP6R7p5oVz7uovub/bZLaBhZc8fo ++z2gAakvYR0o49H7l2XB/LpkOl51yNmj5mZT2Oq1zwKmVkotxiRS3smAZp0CgYAP +sOyFchs3xHVE9GRJe9+6MO8qSXl/p8+DtCMwFTUd+QIYJvwe6lPqNe6Go/zlwbqT +c1yS0f+EWODWu9bLF0jnOpWNgtzHz9Skpr+YH8Re6xju7oY4QyhgnJFoBkMe9x5u +FzN1SRPhRHpNcDtEwI9GK2YkfTgoEyTvhSiwIegurQKBgQDGkheCC7hqleNV3lGM +SfMUgyGt/1abZ82eAkdfeUrM37FeSbxuafyp0ICjZY0xsn6RUickHyXBJhkOGSJX +lGSvHwMsnXT30KAGd08ZqWmTSGmH6IrdVhrveY+e18ILXYgAkQ1T9tSKjeyFfK8m +dUWlFZHfdToFu1pn7yBgofMAmw== +-----END PRIVATE KEY----- diff --git a/certs/localhost.pem b/certs/localhost.pem new file mode 100644 index 00000000..8d4df205 --- /dev/null +++ b/certs/localhost.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEdjCCAt6gAwIBAgIQX/6Qs3c+lQq4+pcuUK7a7jANBgkqhkiG9w0BAQsFADCB +lTEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTUwMwYDVQQLDCxzaHVi +QFNodWItTWVtR1BULURyaXZlci5sb2NhbCAoU2h1YmhhbSBOYWlrKTE8MDoGA1UE +AwwzbWtjZXJ0IHNodWJAU2h1Yi1NZW1HUFQtRHJpdmVyLmxvY2FsIChTaHViaGFt +IE5haWspMB4XDTI0MTIxMDE4MTgwMFoXDTI3MDMxMDE4MTgwMFowYDEnMCUGA1UE +ChMebWtjZXJ0IGRldmVsb3BtZW50IGNlcnRpZmljYXRlMTUwMwYDVQQLDCxzaHVi +QFNodWItTWVtR1BULURyaXZlci5sb2NhbCAoU2h1YmhhbSBOYWlrKTCCASIwDQYJ +KoZIhvcNAQEBBQADggEPADCCAQoCggEBAN6dodOiV/L1PNcBR3rTI87VbSanF0NO +7Gvane0FRpAm3lsQbMluzUzSLlhVEr9LG1hlC/KqYjRQso3z568pISkmgOAt8Uoz +brqPMoNJd3lcFDde67Fsqro1XqqhN3B4nTM/RdcNScqhM3p4yRSLyEP0/VNHc6Td +UadPXCx0bTA/BE8Mj+wP3YYBIvhWJTL/UuWuzsaOU4L7szYYygaJ9IeObHbGBn8r +xx0ParXmIkmWF1uALB96NxCU/tyYu1IkcfXzwRl6gU8R81JSlg2CVLWTHQP8sLWi +hNBGQKksCfF6icxBlLk7n+r/PLF+2TIo740idHoO0zRSPx8a7lQPDVMCAwEAAaN2 +MHQwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUFBwMBMB8GA1UdIwQY +MBaAFJ31vDww7/qA2mBtAN3GE+TZCqNeMCwGA1UdEQQlMCOCCWxvY2FsaG9zdIcE +fwAAAYcQAAAAAAAAAAAAAAAAAAAAATANBgkqhkiG9w0BAQsFAAOCAYEAAy63DbPf +8iSWYmVgccFc5D+MpNgnWi6WsI5OTtRv66eV9+Vv9HseEVrSw8IVMoZt+peosi+K +0woVPT+bKCxlgkEClO7oZIUEMlzJq9sduISFV5fzFLMq8xhIIO5ud4zs1X/1GlrE +zAdq+YiZnbuKqLFSoPLZGrVclmiI3dLqp0LETZxVOiCGt52RRb87Mt9bQEHnP5LJ +EOJYZ1C7/qDDga3vFJ66Nisy015DpE7XXM5PASElpK9l4+yBOg9UdLSkd0VLm/Jm ++4rskdrSTiomU2TBd6Vys7nrn2K72ZOHOcbfFnPEet9z1L44xaddsaPE52ayu8PO +uxHl7rBr2Kzeuy22ppX09EpPdSnjrG6Sgojv4CCS6n8tAbhat8K0pTrzk1e7L8HT +Qy4P/LlViW56mfyM+02CurxbVOecCDdFPMwY357BXMnL6VmRrDtixh+XIXdyK2zS +aYhsbRFA7VJ1AM57gbPbDJElyIlvVetubilvfuOvvQX46cC/ZX5agzTd +-----END CERTIFICATE----- diff --git a/letta/cli/cli.py b/letta/cli/cli.py index bedab429..81e27c9a 100644 --- a/letta/cli/cli.py +++ b/letta/cli/cli.py @@ -53,6 +53,7 @@ def server( debug: Annotated[bool, typer.Option(help="Turn debugging output on")] = False, ade: Annotated[bool, typer.Option(help="Allows remote access")] = False, # NOTE: deprecated secure: Annotated[bool, typer.Option(help="Adds simple security access")] = False, + localhttps: Annotated[bool, typer.Option(help="Setup local https")] = False, ): """Launch a Letta server process""" if type == ServerChoice.rest_api: diff --git a/letta/server/rest_api/app.py b/letta/server/rest_api/app.py index 321a4882..9b567bf4 100644 --- a/letta/server/rest_api/app.py +++ b/letta/server/rest_api/app.py @@ -175,7 +175,6 @@ def create_application() -> "FastAPI": return JSONResponse(status_code=404, content={"detail": "User not found"}) settings.cors_origins.append("https://app.letta.com") - print(f"▶ View using ADE at: https://app.letta.com/development-servers/local/dashboard") if (os.getenv("LETTA_SERVER_SECURE") == "true") or "--secure" in sys.argv: print(f"▶ Using secure mode with password: {random_password}") @@ -254,9 +253,21 @@ def start_server( # Add the handler to the logger server_logger.addHandler(stream_handler) - print(f"▶ Server running at: http://{host or 'localhost'}:{port or REST_DEFAULT_PORT}\n") - uvicorn.run( - app, - host=host or "localhost", - port=port or REST_DEFAULT_PORT, - ) + if (os.getenv("LOCAL_HTTPS") == "true") or "--localhttps" in sys.argv: + uvicorn.run( + app, + host=host or "localhost", + port=port or REST_DEFAULT_PORT, + ssl_keyfile="certs/localhost-key.pem", + ssl_certfile="certs/localhost.pem", + ) + print(f"▶ Server running at: https://{host or 'localhost'}:{port or REST_DEFAULT_PORT}\n") + else: + uvicorn.run( + app, + host=host or "localhost", + port=port or REST_DEFAULT_PORT, + ) + print(f"▶ Server running at: http://{host or 'localhost'}:{port or REST_DEFAULT_PORT}\n") + + print(f"▶ View using ADE at: https://app.letta.com/development-servers/local/dashboard")