Files
landing/README.md
2026-02-13 14:50:12 -03:00

144 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# mifi.holdings — Landing Page
Static landing site for **mifi.holdings** (and www). Plain HTML/CSS, no framework; served by **nginx** in Docker behind **Traefik**, with CI/CD via **Woodpecker** and deployment via **Portainer**.
---
## Quick reference
| What | Where |
| ----------------------- | -------------------------------------------- |
| **Site** | `mifi.holdings`, `www.mifi.holdings` (HTTPS) |
| **Runtime** | nginx (Alpine) in Docker |
| **Reverse proxy / TLS** | Traefik (Let's Encrypt) |
| **CI/CD** | Woodpecker (ci → build → deploy) |
| **Registry** | `git.mifi.dev/mifi-holdings/landing` |
| **Package manager** | pnpm |
---
## Architecture
```
┌─────────────────┐
│ Traefik │ (routing, TLS, websecure)
└────────┬────────┘
┌────────▼────────┐
│ Docker container │ mifi-holdings-landing
│ nginx:alpine │ port 80
│ /usr/share/ │
│ nginx/html ← │ static files from image
└─────────────────┘
```
- **Build**: Docker image = `nginx:alpine` + project `nginx/conf.d/` + `src/` copied into `/usr/share/nginx/html`.
- **Run**: Single service on external network `marina-net`; Traefik routes `mifi.holdings` and `www.mifi.holdings` to this container (HTTPS, `security-prison@file` middleware).
---
## Repo structure
```
.
├── src/ # Static site (served as-is)
│ ├── index.html
│ └── css/
│ └── style.css
├── nginx/
│ └── conf.d/
│ └── default.conf # nginx server config (cache rules, SPA fallback)
├── .woodpecker/
│ ├── ci.yml # Lint + format check (PR + push to main)
│ ├── build.yml # Build image, push to registry (main)
│ └── deploy.yml # Trigger Portainer redeploy (main)
├── docker-compose.yml # Service + Traefik labels for production
├── Dockerfile # nginx + config + src
├── package.json # pnpm scripts: format, lint, docker build/push
└── README.md
```
---
## Tech stack
- **Frontend**: Static HTML + CSS only (no JS build step).
- **Server**: nginx (Alpine) in Docker.
- **Tooling**: **pnpm** (format with Prettier, lint with yamllint for `.woodpecker/*.yml` and `docker-compose.yml`).
- **Deployment**: Docker image → Gitea registry → Portainer stack redeploy.
---
## Local development
- **Dependencies**: `pnpm install` (only devDependencies: Prettier, yaml-lint).
- **Format**: `pnpm format` / `pnpm format:check`.
- **Lint**: `pnpm lint` (yamllint on Woodpecker and docker-compose YAML).
- **Run locally (Docker)**:
- Build: `pnpm docker:build` (or `docker build --platform linux/amd64 -t git.mifi.dev/mifi-holdings/landing:latest .`).
- Run: use `docker-compose up` **only** on a host that has `marina-net` and Traefik; otherwise run the image with a port map and open `http://localhost:<port>`.
There is no dev server in this repo; edit `src/` and refresh the browser or rebuild the image to test.
---
## Docker
- **Dockerfile**: Copies `nginx/conf.d/` and `src/` into an `nginx:alpine` image. No multi-stage build; the image is the final runtime.
- **Image**: Tagged as `git.mifi.dev/mifi-holdings/landing:latest` (and `:<commit-sha>` in CI).
- **Local build/push**: `pnpm docker:build`, `pnpm docker:push` (requires login to `git.mifi.dev`).
---
## CI/CD (Woodpecker)
Three pipelines:
1. **ci** (`.woodpecker/ci.yml`)
- **When**: Every PR and every push to `main`.
- **Steps**: Install deps → Prettier format check → yamllint (Woodpecker + docker-compose). Mattermost notifications on success/failure.
2. **build** (`.woodpecker/build.yml`)
- **When**: Push/tag/manual on `main` (and deployment to production); **depends_on: ci**.
- **Steps**: Build Docker image (linux/amd64, up to 3 retries) → push `:latest` and `:<CI_COMMIT_SHA>` to `git.mifi.dev/mifi-holdings/landing`. Mattermost notifications.
3. **deploy** (`.woodpecker/deploy.yml`)
- **When**: Same as build (main / production deploy); **depends_on: ci**.
- **Steps**: Call Portainer webhook to redeploy the stack. Mattermost notifications.
Secrets used: `gitea_registry_username`, `gitea_package_token`, `portainer_webhook_url`, `mattermost_*` (bot token, channel IDs, API URL).
---
## Deployment (production)
- **Orchestration**: Stack defined in `docker-compose.yml`, deployed via **Portainer** (webhook triggered by Woodpecker deploy pipeline).
- **Network**: Container joins external network `marina-net` (shared with Traefik).
- **Traefik**:
- Hosts: `mifi.holdings`, `www.mifi.holdings`.
- Entrypoint: `websecure` (HTTPS).
- TLS: Let's Encrypt (`tls.certresolver=letsencrypt`).
- Middleware: `security-prison@file`.
- Backend: this service, port 80.
- **Healthcheck**: `wget --spider -q http://localhost/` every 20s (timeout 3s, 3 retries).
To deploy manually: pull the latest image and redeploy the stack in Portainer, or trigger the Portainer webhook (e.g. same URL as in `portainer_webhook_url`).
---
## nginx behavior
- **Root**: `/usr/share/nginx/html` (contents of `src/`).
- **HTML**: `Cache-Control: public, no-cache` so updates are visible quickly.
- **JS/CSS**: Long cache, `immutable` for hashed/versioned assets.
- **Images/fonts**: Cached (30d / 1y).
- **SPA-style fallback**: `/` tries `$uri`, `$uri/`, then `index.html`, then 404.
---
## Summary
- **What it is**: Static landing for mifi.holdings.
- **How it runs**: nginx in Docker, fronted by Traefik on `marina-net`.
- **How its updated**: Push to `main` → Woodpecker runs ci, build (image + push), deploy (Portainer webhook); Mattermost reports status.