feat: provision precipitation storage directory

Create managed StorageBox directories from Ansible and document the precipitation image bind mount required by the test Swarm deployment.
This commit is contained in:
Murat ÖZDEMİR 2026-05-14 19:14:53 +03:00
parent bf64c2964c
commit 49ea69d805
5 changed files with 63 additions and 10 deletions

View File

@ -38,3 +38,12 @@
content: "mounted by ansible" content: "mounted by ansible"
dest: "{{ storagebox_mount_point }}/.mounted_marker" dest: "{{ storagebox_mount_point }}/.mounted_marker"
mode: '0644' mode: '0644'
- name: Create managed StorageBox directories
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
owner: "{{ item.owner | default(omit) }}"
group: "{{ item.group | default(omit) }}"
mode: "{{ item.mode | default('0755') }}"
loop: "{{ storagebox_managed_directories | default([]) }}"

View File

@ -3,6 +3,9 @@ storagebox_user: "{{ storagebox_account }}-sub4"
storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/" storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/"
storagebox_mount_point: "/mnt/storagebox" storagebox_mount_point: "/mnt/storagebox"
storagebox_password: "{{ vault_storagebox_password }}" storagebox_password: "{{ vault_storagebox_password }}"
storagebox_managed_directories:
- path: "{{ storagebox_mount_point }}/precipitation/images"
mode: "0755"
iklim_password: "{{ vault_iklim_password }}" iklim_password: "{{ vault_iklim_password }}"
swarm_manager_ip: "10.10.10.11" swarm_manager_ip: "10.10.10.11"
admin_allowed_cidrs: "78.187.87.109/32 95.70.151.248/32" admin_allowed_cidrs: "78.187.87.109/32 95.70.151.248/32"

View File

@ -151,3 +151,7 @@ Final step order in the pipeline:
`test/secrets/iklim.co/.env` before the first deploy. `test/secrets/iklim.co/.env` before the first deploy.
- `RESTRICTED_IP_1` and `RESTRICTED_IP_2` are hardcoded in the pipeline step above. - `RESTRICTED_IP_1` and `RESTRICTED_IP_2` are hardcoded in the pipeline step above.
Move to `.env` if they change often. Move to `.env` if they change often.
- Precipitation service expects its image-data bind mount at
`/mnt/storagebox/precipitation/images`. This directory is provisioned by the
test Ansible bootstrap through `storagebox_managed_directories`; do not rely on
the deploy pipeline to create it.

View File

@ -20,7 +20,22 @@ docker service ps iklimco_apisix
No tasks in `Failed` or `Rejected` state. No tasks in `Failed` or `Rejected` state.
## 2 — SWAG obtained the cert ## 2 — Precipitation image directory exists
```bash
ls -ld /mnt/storagebox/precipitation/images
```
Expected: directory exists with `0755` permissions or stricter service-approved
permissions before `iklimco_precipitation-service` is deployed.
```bash
docker volume inspect iklimco_image-data
```
Expected: `Options.device` is `/mnt/storagebox/precipitation/images`.
## 3 — SWAG obtained the cert
```bash ```bash
docker exec $(docker ps -q -f name=iklimco_swag) \ docker exec $(docker ps -q -f name=iklimco_swag) \
@ -36,7 +51,7 @@ docker exec $(docker ps -q -f name=iklimco_swag) \
Expected: `fullchain.pem`, `privkey.pem`, `cert.pem`, `chain.pem`. Expected: `fullchain.pem`, `privkey.pem`, `cert.pem`, `chain.pem`.
## 3 — Nginx config is valid ## 4 — Nginx config is valid
```bash ```bash
docker exec $(docker ps -q -f name=iklimco_swag) nginx -t docker exec $(docker ps -q -f name=iklimco_swag) nginx -t
@ -44,7 +59,7 @@ docker exec $(docker ps -q -f name=iklimco_swag) nginx -t
Expected: `syntax is ok` and `test is successful`. Expected: `syntax is ok` and `test is successful`.
## 4 — Public API endpoint ## 5 — Public API endpoint
```bash ```bash
curl -si https://api-test.iklim.co/health curl -si https://api-test.iklim.co/health
@ -60,7 +75,7 @@ echo | openssl s_client -connect api-test.iklim.co:443 -servername api-test.ikli
Expected: `subject=CN=*.iklim.co`, dates valid, `notAfter` > today. Expected: `subject=CN=*.iklim.co`, dates valid, `notAfter` > today.
## 5 — IP-restricted subdomains block non-whitelisted IPs ## 6 — IP-restricted subdomains block non-whitelisted IPs
From a non-whitelisted IP: From a non-whitelisted IP:
```bash ```bash
@ -74,7 +89,7 @@ curl -si https://grafana-test.iklim.co
``` ```
Expected: HTTP 200 (Grafana login page). Expected: HTTP 200 (Grafana login page).
## 6 — Vault is reachable internally (not externally) ## 7 — Vault is reachable internally (not externally)
From outside the server: From outside the server:
```bash ```bash
@ -91,14 +106,14 @@ docker exec $(docker ps -q -f name=iklimco_apisix | head -1) \
``` ```
Expected: JSON response `{"sealed":false,...}`. Expected: JSON response `{"sealed":false,...}`.
## 7 — cert-reloader is watching ## 8 — cert-reloader is watching
```bash ```bash
docker service logs iklimco_cert-reloader --tail 10 docker service logs iklimco_cert-reloader --tail 10
``` ```
Expected: `[cert-reloader] started` — no errors. Expected: `[cert-reloader] started` — no errors.
## 8 — Vault cert path is correct ## 9 — Vault cert path is correct
```bash ```bash
VAULT_CTR=$(docker ps -q -f name=iklimco_vault) VAULT_CTR=$(docker ps -q -f name=iklimco_vault)
@ -106,7 +121,7 @@ docker exec "$VAULT_CTR" ls /vault/certs/
``` ```
Expected: `STAR.iklim.co.full.crt` and `STAR.iklim.co_key.txt`. Expected: `STAR.iklim.co.full.crt` and `STAR.iklim.co_key.txt`.
## 9 — fail2ban is active (SWAG) ## 10 — fail2ban is active (SWAG)
```bash ```bash
docker exec $(docker ps -q -f name=iklimco_swag) \ docker exec $(docker ps -q -f name=iklimco_swag) \
@ -114,7 +129,7 @@ docker exec $(docker ps -q -f name=iklimco_swag) \
``` ```
Expected: list of jails including `nginx-http-auth`, `nginx-botsearch`, etc. Expected: list of jails including `nginx-http-auth`, `nginx-botsearch`, etc.
## 10 — No services have published unexpected ports ## 11 — No services have published unexpected ports
```bash ```bash
docker service ls --format "{{.Name}}\t{{.Ports}}" \ docker service ls --format "{{.Name}}\t{{.Ports}}" \

View File

@ -317,6 +317,9 @@ storagebox_user: "{{ storagebox_account }}-sub4"
storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/" storagebox_url: "https://{{ storagebox_user }}.your-storagebox.de/"
storagebox_password: "{{ vault_storagebox_password }}" storagebox_password: "{{ vault_storagebox_password }}"
storagebox_mount_point: "/mnt/storagebox" storagebox_mount_point: "/mnt/storagebox"
storagebox_managed_directories:
- path: "{{ storagebox_mount_point }}/precipitation/images"
mode: "0755"
``` ```
Prod ortamında suffix `sub4``sub5` olarak değişir. Prod ortamında suffix `sub4``sub5` olarak değişir.
@ -398,12 +401,31 @@ vault_iklim_password: "IKLIM_KULLANICI_PAROLASI"
dest: "{{ storagebox_mount_point }}/.mounted_marker" dest: "{{ storagebox_mount_point }}/.mounted_marker"
``` ```
6. **Servis bind mount dizinlerini oluştur**
Test ortamında precipitation servisinin `image-data` volume'u host üzerinde
`/mnt/storagebox/precipitation/images` dizinine bind mount edilir. Dizin
StorageBox mount edildikten sonra Ansible tarafından oluşturulur ve `0755`
izinle bırakılır.
```yaml
- name: Create managed StorageBox directories
ansible.builtin.file:
path: "{{ item.path }}"
state: directory
owner: "{{ item.owner | default(omit) }}"
group: "{{ item.group | default(omit) }}"
mode: "{{ item.mode | default('0755') }}"
loop: "{{ storagebox_managed_directories | default([]) }}"
```
### Notlar ### Notlar
- `davfs2` paketi EPEL repository'sinde bulunur; base role `epel-release`'i zaten kurar. - `davfs2` paketi EPEL repository'sinde bulunur; base role `epel-release`'i zaten kurar.
- StorageBox şifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur. - StorageBox şifreleri asla plaintext olarak repository'e eklenmez; Ansible Vault zorunludur.
- Mount noktası reboot'ta `_netdev` flag'ı sayesinde network hazır olduktan sonra otomatik mount edilir. - Mount noktası reboot'ta `_netdev` flag'ı sayesinde network hazır olduktan sonra otomatik mount edilir.
- Docker Swarm servisleri `/mnt/storagebox/<env>/<service>/` altındaki dizinleri bind mount olarak kullanır. - Docker Swarm servisleri StorageBox altındaki servis dizinlerini bind mount olarak kullanır.
- Precipitation servisinin test ortamı image dizini `/mnt/storagebox/precipitation/images` olmalıdır; bu path `BE-Precipitation/docker-stack-service.yml` içindeki `device` değeriyle birebir eşleşmelidir.
## StorageBox SSH Key Role ## StorageBox SSH Key Role