Skip to content

Commit 29d47e5

Browse files
Added basic deployment instructions to docs
1 parent 887001c commit 29d47e5

File tree

5 files changed

+42
-67
lines changed

5 files changed

+42
-67
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
__pycache__
33
*.pyc
44
.env
5+
.env.local
6+
.env.development
7+
.env.production
58
_environment
69
/.quarto/
710
_docs/

docs/deployment.qmd

Lines changed: 38 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,6 @@ doctl projects list
3131
doctl projects create --name "YOUR-PROJECT-NAME" --purpose "YOUR-PROJECT-PURPOSE" --environment "Production"
3232
```
3333

34-
Take note of the Project ID in the output for later use.
35-
3634
#### Set Up a Managed PostgreSQL Database
3735

3836
Create a managed, serverless PostgreSQL database instance:
@@ -44,11 +42,8 @@ doctl databases create your-db-name --engine pg --version 17 --size db-s-1vcpu-1
4442
Get the database ID from the output of the create command and use it to retrieve the database connection details:
4543

4644
```bash
47-
# Get the database ID from the output of the create command
48-
DATABASE_ID="your-database-id"
49-
50-
# Get connection details
51-
doctl databases connection $DATABASE_ID --format Host,Port,User,Password,Database
45+
# Get the database connection details
46+
doctl databases connection "your-database-id" --format Host,Port,User,Password,Database
5247
```
5348

5449
Store these details securely in a `.env.production` file (you will need to set them later in application deployment as production secrets):
@@ -94,29 +89,6 @@ The disadvantages are:
9489
- Install modal in the project directory with `uv add modal`
9590
- Run `uv run modal setup` to authenticate with Modal
9691

97-
#### Setting Up Modal Secrets
98-
99-
The application relies on environment variables stored in `.env` (like `SECRET_KEY`, `DB_USER`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `RESEND_API_KEY`, `BASE_URL`). These sensitive values should be stored securely using Modal Secrets.
100-
101-
Create a Modal Secret (e.g., named `fastapi-webapp-secrets`) either through the Modal UI or CLI:
102-
103-
```bash
104-
# Example using CLI
105-
modal secret create your-app-name-secret \
106-
SECRET_KEY='your_actual_secret_key' \
107-
DB_USER='your_db_user' \
108-
DB_PASSWORD='your_db_password' \
109-
DB_HOST='your_external_db_host' \
110-
DB_PORT='your_db_port' \
111-
DB_NAME='your_db_name' \
112-
RESEND_API_KEY='your_resend_api_key' \
113-
BASE_URL='https://your-username--your-app-name-serve.modal.run'
114-
```
115-
116-
You can probably guess what the `BASE_URL` will be from your user/organization name and the name of the Modal app, but you can also update it later after you get the official public base URL.
117-
118-
**Important:** Ensure `DB_HOST` points to your *cloud* database host address, not `localhost` or `host.docker.internal`.
119-
12092
#### Defining the Modal Image and App
12193

12294
Create a new Python file in the root of your project, for example, `deploy.py`. This file will define the Modal Image and the ASGI app deployment.
@@ -138,24 +110,20 @@ Create a new Python file in the root of your project, for example, `deploy.py`.
138110
image = (
139111
modal.Image.debian_slim(python_version="3.13")
140112
.apt_install("libpq-dev", "libwebp-dev")
141-
.pip_install("uv")
142-
.run_commands(
143-
# Install dependencies from pyproject.toml using uv
144-
# Make sure uv sync handles psycopg2 correctly with libpq-dev present
145-
"uv sync --no-dev --system --compile-bytecode",
146-
)
113+
.pip_install_from_pyproject("pyproject.toml")
114+
.add_local_python_source("main")
147115
.add_local_python_source("routers")
148116
.add_local_python_source("utils")
149117
.add_local_python_source("exceptions")
150-
.add_local_dir("static", remote_path="/static")
151-
.add_local_dir("templates", remote_path="/templates")
118+
.add_local_dir("static", remote_path="/root/static")
119+
.add_local_dir("templates", remote_path="/root/templates")
152120
)
153121

154122
# Define the Modal App
155123
app = modal.App(
156-
name="fastapi-webapp", # Optional: name for your Modal app
124+
name="your-app-name",
157125
image=image,
158-
secrets=[modal.Secret.from_name("fastapi-webapp-secrets")]
126+
secrets=[modal.Secret.from_name("your-app-name-secret")]
159127
)
160128
```
161129

@@ -188,16 +156,35 @@ For more information on Modal FastAPI images and applications, see [this guide](
188156

189157
#### Deploying the App
190158

191-
1. From your terminal, in the root directory of your project, run:
192-
```bash
193-
modal deploy deploy.py
194-
```
195-
Modal will build the image (if it hasn't been built before or if dependencies changed) and deploy the ASGI app. It will output a public URL (e.g., `https://your-username--your-app-name.modal.run`).
159+
From your terminal, in the root directory of your project, run:
196160

197-
2. Once you have the public URL from Modal, make sure the `BASE_URL` variable in your Modal Secret matches this public URL. This is crucial for generating correct absolute URLs (e.g., in password reset emails). If you need to update the secret, run:
198-
```bash
199-
modal secret update your-app-name-secret BASE_URL='https://your-modal-app-url'
200-
```
201-
Redeploy if necessary (`modal deploy deploy.py`), although changes to secrets often take effect on subsequent container starts without a full redeploy.
161+
```bash
162+
modal deploy deploy.py
163+
```
164+
165+
Modal will build the image (if it hasn't been built before or if dependencies changed) and deploy the ASGI app. It will output a public URL (e.g., `https://your-username--your-app-name.modal.run`).
166+
167+
#### Setting Up Modal Secrets
168+
169+
The application relies on environment variables stored in `.env` (like `SECRET_KEY`, `DB_USER`, `DB_PASSWORD`, `DB_HOST`, `DB_PORT`, `DB_NAME`, `RESEND_API_KEY`, `BASE_URL`). These sensitive values should be stored securely using Modal Secrets.
170+
171+
Create a Modal Secret either through the Modal UI or CLI. Note that the name of the secret has to match the secret name you used in the `deploy.py` file, above (e.g., `your-app-name-secret`).
172+
173+
```bash
174+
# Example using CLI
175+
modal secret create your-app-name-secret \
176+
SECRET_KEY='your_actual_secret_key' \
177+
DB_USER='your_db_user' \
178+
DB_PASSWORD='your_db_password' \
179+
DB_HOST='your_external_db_host' \
180+
DB_PORT='your_db_port' \
181+
DB_NAME='your_db_name' \
182+
RESEND_API_KEY='your_resend_api_key' \
183+
BASE_URL='https://your-username--your-app-name-serve.modal.run'
184+
```
185+
186+
**Important:** Ensure `DB_HOST` points to your *cloud* database host address, not `localhost` or `host.docker.internal`.
187+
188+
#### Testing the Deployment
202189

203-
3. Access the provided Modal URL in your browser. Browse the site and test the registration and password reset features to ensure database and Resend connections work correctly.
190+
Access the provided Modal URL in your browser. Browse the site and test the registration and password reset features to ensure database and Resend connections work.

main.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ async def read_home(
188188
user: Optional[User] = Depends(get_optional_user)
189189
):
190190
if user:
191-
return RedirectResponse(url="/dashboard", status_code=302)
191+
return RedirectResponse(url=app.url_path_for("read_dashboard"), status_code=302)
192192
return templates.TemplateResponse(
193193
request,
194194
"index.html",

pyproject.toml

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,5 @@ dev = [
3131
"notebook<8.0.0,>=7.2.2",
3232
"pytest<9.0.0,>=8.3.3",
3333
"sqlalchemy-schemadisplay<3.0,>=2.0",
34-
"perplexity-cli",
3534
"mypy>=1.15.0",
3635
]
37-
38-
[tool.uv.sources]
39-
perplexity-cli = { git = "https://github.com/chriscarrollsmith/perplexity-cli.git" }

uv.lock

Lines changed: 0 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)