Serve the CMS admin panel under /admin on the public domain
Replace the separate CMS subdomain with path-based routing in Caddy: /admin and /uploads go to Strapi, everything else to the frontend. Strapi 5 nests its whole admin panel (UI and API) under /admin, so this one prefix is enough and never collides with the frontend's own /api routes. Drops CMS_DOMAIN and the unused STRAPI_URL env var on the cms service; PUBLIC_STRAPI_URL now points at the same origin as the site. Authentication is unchanged: Strapi's own admin login still gates the panel, this only changes how it's reached.
This commit is contained in:
@@ -4,8 +4,8 @@ Blog platform: a public website built with Nuxt, and a private Strapi CMS where
|
||||
articles are written. Everything runs behind Caddy via Docker Compose.
|
||||
|
||||
```text
|
||||
Browser → Caddy ─┬─ public domain → Nuxt (website)
|
||||
└─ cms subdomain → Strapi (CMS) → PostgreSQL
|
||||
Browser → Caddy ─┬─ /admin, /uploads → Strapi (CMS) → PostgreSQL
|
||||
└─ everything else → Nuxt (website)
|
||||
```
|
||||
|
||||
There are no front-end accounts: sign-up is disabled and only administrators write
|
||||
@@ -46,7 +46,8 @@ The first build takes a few minutes. `docker-compose.dev.yml` publishes the port
|
||||
`127.0.0.1` and leaves Caddy out; it must always be passed explicitly, so it can never be
|
||||
picked up by accident in production.
|
||||
|
||||
**4. Create the administrator account** at http://localhost:1337/admin. This is the first
|
||||
**4. Create the administrator account** at http://localhost:1337/admin (dev bypasses Caddy,
|
||||
so the CMS is reached directly on its port). This is the first
|
||||
run, so the form creates the account — pick your own credentials.
|
||||
|
||||
**5. Write something.** In the admin panel: create a **Category**, then an **Article**
|
||||
@@ -72,16 +73,15 @@ override it with `NUXT_STRAPI_URL` if needed. Strapi reads its own `cms/.env`.
|
||||
|
||||
## Production
|
||||
|
||||
**1. Point the DNS at the server.** Two `A` records (and `AAAA` if you have IPv6) on the
|
||||
**1. Point the DNS at the server.** One `A` record (and `AAAA` if you have IPv6) on the
|
||||
public IP of the machine:
|
||||
|
||||
| Record | Purpose |
|
||||
|---|---|
|
||||
| `example.com` | the website |
|
||||
| `cms.example.com` | the Strapi admin panel |
|
||||
| `example.com` | the website and, at `/admin`, the Strapi admin panel |
|
||||
|
||||
Wait for the records to resolve before starting the stack — Caddy requests the
|
||||
certificates on the first boot and a failed challenge means a retry delay.
|
||||
Wait for the record to resolve before starting the stack — Caddy requests the
|
||||
certificate on the first boot and a failed challenge means a retry delay.
|
||||
|
||||
**2. Open the firewall** for ports `80` and `443` only. Port `80` is required: Caddy uses
|
||||
it for the ACME challenge and to redirect to HTTPS. PostgreSQL, Strapi and Nuxt are only
|
||||
@@ -92,10 +92,9 @@ reachable inside the Docker network — do not publish their ports.
|
||||
| Variable | Value |
|
||||
|---|---|
|
||||
| `PUBLIC_DOMAIN` | `example.com` |
|
||||
| `CMS_DOMAIN` | `cms.example.com` |
|
||||
| `ACME_EMAIL` | a mailbox you read — Let's Encrypt sends expiry warnings there |
|
||||
| `PUBLIC_SITE_URL` | `https://example.com` |
|
||||
| `PUBLIC_STRAPI_URL` | `https://cms.example.com` |
|
||||
| `PUBLIC_STRAPI_URL` | `https://example.com` — same origin, Caddy proxies `/admin` and `/uploads` to Strapi |
|
||||
| `STRAPI_URL` | leave it as `http://cms:1337` — internal address, never public |
|
||||
|
||||
Then generate **fresh** secrets on that machine with the same loop as in development —
|
||||
@@ -112,11 +111,11 @@ already ignored.
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
This time Caddy is included: it serves the website on `PUBLIC_DOMAIN`, the CMS on
|
||||
`CMS_DOMAIN`, obtains and renews the TLS certificates on its own, and adds HSTS and the
|
||||
other security headers.
|
||||
This time Caddy is included: it serves both the website and, under `/admin` and
|
||||
`/uploads`, the CMS on `PUBLIC_DOMAIN`, obtains and renews the TLS certificate on its own,
|
||||
and adds HSTS and the other security headers.
|
||||
|
||||
**5. Create the administrator account** at `https://cms.example.com/admin`, immediately,
|
||||
**5. Create the administrator account** at `https://example.com/admin`, immediately,
|
||||
before anyone else finds the URL — the first visitor to that form is the one who gets the
|
||||
account. Then publish as in development.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user