Compare commits

..

2 Commits

Author SHA1 Message Date
bisco 5bdf628a2e docs: add first startup procedure 2026-06-25 12:26:55 +02:00
bisco 0302634094 fix: keep proxy healthy during tls pending 2026-06-25 12:00:33 +02:00
4 changed files with 118 additions and 3 deletions
+88
View File
@@ -45,6 +45,85 @@ Open:
Use the development credentials copied into `.env` only locally. Change them before Use the development credentials copied into `.env` only locally. Change them before
sharing the environment. sharing the environment.
## First startup procedure
Use this checklist for the first run of a new environment.
1. Create the environment file:
```bash
cp .env.example .env
```
2. Edit `.env` before starting containers:
- set strong `MARIADB_PASSWORD`, `MARIADB_ROOT_PASSWORD`, and `WP_ADMIN_PASSWORD`;
- set `WP_URL` to the public URL, for example `https://lab.younerd.org`;
- set `LETSENCRYPT_DOMAIN` to the same hostname when direct Let's Encrypt is used;
- keep `LETSENCRYPT_STAGING=1` for the first certificate test;
- configure `DB_DATA_PATH`, `WORDPRESS_DATA_PATH`, `LETSENCRYPT_DATA_PATH`, and
`CERTBOT_CHALLENGES_PATH` for the host directories that must persist.
3. Prepare host-based volumes and permissions:
```bash
./scripts/prepare-host-volumes.sh
```
On Linux hosts, rerun with `sudo` if the script warns that it cannot change
ownership:
```bash
sudo ./scripts/prepare-host-volumes.sh
```
4. Start the runtime services:
```bash
docker compose up --build -d
docker compose ps
```
With `LETSENCRYPT_ENABLED=1` and no certificate yet, NGINX intentionally returns
`503` for normal application traffic while still serving ACME challenge and health
routes. Certbot should start after the proxy becomes healthy.
5. Install/configure WordPress on the real persistent volume:
```bash
docker compose --profile tools run --rm wp-cli /scripts/bootstrap.sh
```
Do not add `-f docker-compose.test.yml` here. The test override uses disposable test
volumes and is only for automated checks.
6. Follow certificate issuance:
```bash
docker compose logs -f proxy certbot
```
After the staging certificate flow is working, switch to the production CA:
```dotenv
LETSENCRYPT_STAGING=0
```
Then restart the affected services:
```bash
docker compose up -d proxy certbot
```
7. Final sanity checks:
```bash
docker compose ps
docker compose logs --tail=100 proxy wordpress db certbot
```
Open the configured `WP_URL` and `/wp-admin/`.
Persistent data uses host-based bind mounts by default: Persistent data uses host-based bind mounts by default:
- `./runtime/db` for MariaDB; - `./runtime/db` for MariaDB;
@@ -102,6 +181,15 @@ TRUST_PROXY_HEADERS=0
Before the first certificate exists, NGINX serves ACME challenges and returns 503 for Before the first certificate exists, NGINX serves ACME challenges and returns 503 for
application traffic. After issuance, HTTP redirects to HTTPS automatically. application traffic. After issuance, HTTP redirects to HTTPS automatically.
Run the real bootstrap without the test override:
```bash
docker compose --profile tools run --rm wp-cli /scripts/bootstrap.sh
```
The `docker-compose.test.yml` override intentionally uses disposable test volumes; do
not use it for production or staging bootstrap commands.
## Useful commands ## Useful commands
```bash ```bash
+4 -3
View File
@@ -42,9 +42,10 @@ is safe only when firewall/network policy makes the load balancer the sole NGINX
caller and it overwrites `X-Forwarded-*` headers. caller and it overwrites `X-Forwarded-*` headers.
For direct TLS, public DNS and inbound ports 80/443 must reach NGINX. Start with For direct TLS, public DNS and inbound ports 80/443 must reach NGINX. Start with
`LETSENCRYPT_STAGING=1`; application HTTP returns 503 until a certificate exists, then `LETSENCRYPT_STAGING=1` and set `WP_URL` to the final HTTPS URL. Application HTTP
redirects to HTTPS. Switch to the production CA only after validating DNS and firewall returns 503 until a certificate exists, then redirects to HTTPS. Switch to the
behavior, removing only the staging certificate volume when necessary. production CA only after validating DNS and firewall behavior, removing only the
staging certificate directory when necessary.
## State and rollback ## State and rollback
+19
View File
@@ -31,6 +31,25 @@ Verify public DNS, inbound port 80, the operator email, and staging mode. Reques
missing `/.well-known/acme-challenge/` path: an NGINX 404 confirms the route is yours. missing `/.well-known/acme-challenge/` path: an NGINX 404 confirms the route is yours.
Avoid repeated production-CA retries while debugging. Avoid repeated production-CA retries while debugging.
When Let's Encrypt is enabled, the proxy intentionally returns 503 for normal
application paths until a certificate exists. ACME challenge paths and proxy health
paths must still work in that pending state, otherwise Certbot will never start.
## Bootstrap writes to the wrong data volume
Do not combine the test override with production bootstrap commands. This command writes
to isolated test volumes only:
```bash
docker compose -f docker-compose.yml -f docker-compose.test.yml --profile tools run --rm wp-cli /scripts/bootstrap.sh
```
Use this command for the real host-based WordPress data directory:
```bash
docker compose --profile tools run --rm wp-cli /scripts/bootstrap.sh
```
## Rollback ## Rollback
Revert the deployment commit and rebuild while preserving all host data directories. Revert the deployment commit and rebuild while preserving all host data directories.
+7
View File
@@ -29,10 +29,17 @@ server {
access_log off; access_log off;
allow 127.0.0.1; allow 127.0.0.1;
deny all; deny all;
proxy_intercept_errors on;
error_page 301 302 303 307 308 = @wordpress-health-ok;
proxy_set_header Host __DOMAIN__; proxy_set_header Host __DOMAIN__;
proxy_pass http://wordpress_backend/wp-login.php; proxy_pass http://wordpress_backend/wp-login.php;
} }
location @wordpress-health-ok {
access_log off;
return 204;
}
location / { location / {
return 404; return 404;
} }