Align deploy with central nginx: host-published 2569 + paste-in vhost (manual certs)
- Central nginx is containerized and proxies via host IP (171.22.25.73:port), not localhost → publish app on host :2569 (was 127.0.0.1)
- nginx vhost rewritten to match the monolithic config style (server blocks to paste into http{}, manual /etc/ssl/hamkadr certs, proxy_pass 171.22.25.73:2569, $connection_upgrade)
- DEPLOY.md: corrected architecture/ports, removed certbot+sites-available (use manual certs + single nginx.conf)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -7,22 +7,25 @@ TLS for `hamkadr.ir` and reverse-proxies to the app.
|
|||||||
## Architecture & open ports
|
## Architecture & open ports
|
||||||
|
|
||||||
```
|
```
|
||||||
Internet ──443/80──► nginx (host, existing) ──► 127.0.0.1:2569 ──► hamkadr_api (container :8080)
|
Internet ─443/80─► central nginx (container) ─► http://171.22.25.73:2569 ─► hamkadr_api (container :8080)
|
||||||
│ internal docker net
|
(nexus/mirror/gitea/meezi…) host-published port │ internal docker net
|
||||||
▼
|
▼
|
||||||
hamkadr_db (postgres, no host port)
|
hamkadr_db (postgres, no host port)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Matches the existing soroush pattern: the **containerized** central nginx reaches each app via the
|
||||||
|
**host IP + published port** (`171.22.25.73:<port>`), not localhost. So hamkadr publishes `2569` on
|
||||||
|
the host (like meezi 5080, draletaha 5010…).
|
||||||
|
|
||||||
| Port | Open? | Purpose |
|
| Port | Open? | Purpose |
|
||||||
|------|-------|---------|
|
|------|-------|---------|
|
||||||
| 22 | ✅ (ideally IP-restricted) | SSH |
|
| 22 | ✅ (ideally IP-restricted) | SSH |
|
||||||
| 80 | ✅ | HTTP → 443 redirect + Let's Encrypt ACME |
|
| 80 / 443 | ✅ (already open) | central nginx — serves `hamkadr.ir` too |
|
||||||
| 443 | ✅ | HTTPS `hamkadr.ir` |
|
| 2569 | host-published | app; only nginx proxies to it. Optionally firewall to the nginx host. |
|
||||||
| 2569 | ❌ host-localhost only | app, reached only by nginx |
|
|
||||||
| 5432 | ❌ internal docker net only | Postgres — never published |
|
| 5432 | ❌ internal docker net only | Postgres — never published |
|
||||||
|
|
||||||
`ufw` should be exactly: `allow 22, 80, 443`. Nothing else. (80/443 are already open since nginx
|
No firewall change needed for 80/443 (nginx already serves git./mirror./meezi). 2569 is published
|
||||||
serves git./mirror. — no firewall change needed.)
|
on the host like the other apps.
|
||||||
|
|
||||||
## Files in this repo
|
## Files in this repo
|
||||||
|
|
||||||
@@ -30,7 +33,7 @@ serves git./mirror. — no firewall change needed.)
|
|||||||
|------|------|
|
|------|------|
|
||||||
| `Dockerfile` | multi-stage build, images + NuGet via `mirror.soroushasadi.com` |
|
| `Dockerfile` | multi-stage build, images + NuGet via `mirror.soroushasadi.com` |
|
||||||
| `nuget.docker.config` | NuGet → Nexus `nuget-group` |
|
| `nuget.docker.config` | NuGet → Nexus `nuget-group` |
|
||||||
| `docker-compose.yml` | production stack: `api` (127.0.0.1:${HOST_PORT}) + `db` (internal) + named volume |
|
| `docker-compose.yml` | production stack: `api` (host :${HOST_PORT}) + `db` (internal) + named volume |
|
||||||
| `docker-compose.dev.yml` | local-dev Postgres only (host 5433) for `dotnet run` |
|
| `docker-compose.dev.yml` | local-dev Postgres only (host 5433) for `dotnet run` |
|
||||||
| `.gitea/workflows/ci-cd.yml` | build job + self-hosted deploy (backup → rollback tag → recreate → health-wait) |
|
| `.gitea/workflows/ci-cd.yml` | build job + self-hosted deploy (backup → rollback tag → recreate → health-wait) |
|
||||||
| `deploy/nginx-hamkadr.ir.conf` | nginx vhost for hamkadr.ir |
|
| `deploy/nginx-hamkadr.ir.conf` | nginx vhost for hamkadr.ir |
|
||||||
@@ -38,10 +41,10 @@ serves git./mirror. — no firewall change needed.)
|
|||||||
## One-time setup
|
## One-time setup
|
||||||
|
|
||||||
### 1. DNS
|
### 1. DNS
|
||||||
A records → server IP:
|
A records → 171.22.25.73:
|
||||||
```
|
```
|
||||||
hamkadr.ir A <server-ip>
|
hamkadr.ir A 171.22.25.73
|
||||||
www.hamkadr.ir A <server-ip>
|
www.hamkadr.ir A 171.22.25.73
|
||||||
```
|
```
|
||||||
|
|
||||||
### 2. Gitea runner
|
### 2. Gitea runner
|
||||||
@@ -74,13 +77,22 @@ ADMIN_PHONE=09XXXXXXXXX
|
|||||||
> `ASPNETCORE_ENVIRONMENT=Production` is set by the compose file ⇒ only **reference data**
|
> `ASPNETCORE_ENVIRONMENT=Production` is set by the compose file ⇒ only **reference data**
|
||||||
> (roles/cities/districts) is seeded — no demo facilities/shifts.
|
> (roles/cities/districts) is seeded — no demo facilities/shifts.
|
||||||
|
|
||||||
### 4. nginx vhost + TLS
|
### 4. TLS cert + nginx vhost
|
||||||
```bash
|
Your central nginx is a **single monolithic `nginx.conf`** with **manually-placed certs** (no
|
||||||
sudo cp deploy/nginx-hamkadr.ir.conf /etc/nginx/sites-available/hamkadr.ir
|
certbot). Match that:
|
||||||
sudo ln -s /etc/nginx/sites-available/hamkadr.ir /etc/nginx/sites-enabled/
|
|
||||||
sudo nginx -t && sudo systemctl reload nginx
|
1. Put the hamkadr.ir cert where nginx expects (same convention as your other domains):
|
||||||
sudo certbot --nginx -d hamkadr.ir -d www.hamkadr.ir
|
```
|
||||||
```
|
/etc/ssl/hamkadr/fullchain.pem
|
||||||
|
/etc/ssl/hamkadr/privateKey.pem
|
||||||
|
```
|
||||||
|
2. Paste the two `server { }` blocks from `deploy/nginx-hamkadr.ir.conf` **into the `http { }`
|
||||||
|
block** of your central nginx.conf (next to meezi/draletaha). They proxy to
|
||||||
|
`http://171.22.25.73:2569` and reuse the global `$connection_upgrade` map.
|
||||||
|
3. Reload:
|
||||||
|
```bash
|
||||||
|
nginx -t && nginx -s reload # or: docker exec <nginx-container> nginx -s reload
|
||||||
|
```
|
||||||
|
|
||||||
### 5. First deploy
|
### 5. First deploy
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -1,25 +1,38 @@
|
|||||||
# hamkadr.ir reverse-proxy vhost for the EXISTING nginx on the server.
|
# ============================================================================
|
||||||
# Install:
|
# hamkadr.ir — paste these two server{} blocks INTO the http { } block of your
|
||||||
# sudo cp deploy/nginx-hamkadr.ir.conf /etc/nginx/sites-available/hamkadr.ir
|
# central nginx.conf (the one with nexus/mirror/gitea/meezi), then:
|
||||||
# sudo ln -s /etc/nginx/sites-available/hamkadr.ir /etc/nginx/sites-enabled/
|
# nginx -t && nginx -s reload (or: docker exec <nginx> nginx -s reload)
|
||||||
# sudo nginx -t && sudo systemctl reload nginx
|
|
||||||
# sudo certbot --nginx -d hamkadr.ir -d www.hamkadr.ir # adds the :443 server + HTTP→HTTPS redirect
|
|
||||||
#
|
#
|
||||||
# The port below MUST match HOST_PORT in the Gitea ENV_FILE secret (default 2569).
|
# Prereqs (match your existing pattern):
|
||||||
|
# • TLS cert placed at /etc/ssl/hamkadr/fullchain.pem + privateKey.pem (manual, like your others)
|
||||||
|
# • hamkadr.ir + www.hamkadr.ir A records → 171.22.25.73
|
||||||
|
# • the app published on the host at :2569 (docker-compose.yml) — nginx reaches it via the host IP,
|
||||||
|
# exactly like meezi (5080), draletaha (5010), etc. $connection_upgrade map is already defined globally.
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
server {
|
server {
|
||||||
listen 80;
|
listen 80;
|
||||||
listen [::]:80;
|
|
||||||
server_name hamkadr.ir www.hamkadr.ir;
|
server_name hamkadr.ir www.hamkadr.ir;
|
||||||
|
return 301 https://$host$request_uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
http2 on;
|
||||||
|
server_name hamkadr.ir www.hamkadr.ir;
|
||||||
|
client_max_body_size 25m;
|
||||||
|
|
||||||
|
ssl_certificate /etc/ssl/hamkadr/fullchain.pem;
|
||||||
|
ssl_certificate_key /etc/ssl/hamkadr/privateKey.pem;
|
||||||
|
|
||||||
# The app binds 127.0.0.1:2569 (docker-compose.yml, service "api") — never exposed publicly.
|
|
||||||
location / {
|
location / {
|
||||||
proxy_pass http://127.0.0.1:2569;
|
proxy_pass http://171.22.25.73:2569;
|
||||||
proxy_http_version 1.1;
|
proxy_http_version 1.1;
|
||||||
proxy_set_header Host $host;
|
proxy_set_header Host $host;
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
proxy_set_header X-Forwarded-Proto $scheme; # app's ForwardedHeaders reads this → knows it's HTTPS
|
proxy_set_header X-Forwarded-Proto $scheme; # app's ForwardedHeaders reads this → knows it's HTTPS
|
||||||
proxy_read_timeout 60s;
|
proxy_set_header Upgrade $http_upgrade;
|
||||||
|
proxy_set_header Connection $connection_upgrade;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -17,7 +17,9 @@ services:
|
|||||||
db:
|
db:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:${HOST_PORT:-2569}:8080" # localhost-only; nginx proxies hamkadr.ir → here
|
# Published on the host so the (containerized) central nginx can reach it at
|
||||||
|
# http://171.22.25.73:${HOST_PORT} — same pattern as the other soroush apps.
|
||||||
|
- "${HOST_PORT:-2569}:8080"
|
||||||
environment:
|
environment:
|
||||||
ASPNETCORE_ENVIRONMENT: "Production"
|
ASPNETCORE_ENVIRONMENT: "Production"
|
||||||
ASPNETCORE_URLS: "http://+:8080"
|
ASPNETCORE_URLS: "http://+:8080"
|
||||||
|
|||||||
Reference in New Issue
Block a user