diff --git a/.woodpecker.yml b/.woodpecker.yml index e783fd4..68e40d6 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -14,14 +14,14 @@ steps: - name: build image: docker:latest environment: - REGISTRY_REPO: ${REGISTRY_REPO} + REGISTRY_REPO: git.mifi.dev/mifi-ventures/landing volumes: - /var/run/docker.sock:/var/run/docker.sock commands: - set -e # Exit on error - echo "=== Building Docker image ===" - - echo "Commit SHA: ${CI_COMMIT_SHA:0:8}" - - echo "Registry repo: $REGISTRY_REPO" + - 'echo "Commit SHA: ${CI_COMMIT_SHA:0:8}"' + - 'echo "Registry repo: $REGISTRY_REPO"' - | docker build \ --tag $REGISTRY_REPO:${CI_COMMIT_SHA} \ @@ -37,9 +37,10 @@ steps: - name: push image: docker:latest environment: - REGISTRY_URL: ${REGISTRY_URL} - REGISTRY_REPO: ${REGISTRY_REPO} - REGISTRY_USERNAME: ${REGISTRY_USERNAME} + REGISTRY_URL: git.mifi.dev + REGISTRY_REPO: git.mifi.dev/mifi-ventures/landing + REGISTRY_USERNAME: + from_secret: registry_username REGISTRY_PASSWORD: from_secret: registry_password volumes: @@ -47,8 +48,8 @@ steps: commands: - set -e # Exit on error - echo "=== Pushing to registry ===" - - echo "Registry: $REGISTRY_URL" - - echo "Repository: $REGISTRY_REPO" + - 'echo "Registry: $REGISTRY_URL"' + - 'echo "Repository: $REGISTRY_REPO"' - | echo "$REGISTRY_PASSWORD" | docker login "$REGISTRY_URL" \ -u "$REGISTRY_USERNAME" \ @@ -86,14 +87,14 @@ steps: # Configuration Reference # ============================================ # -# Required Secrets (set in Woodpecker UI): -# - registry_password: Gitea container registry password/token +# Woodpecker has no separate "Variables" UI — use Secrets for everything. +# +# Required Secrets (Repo → Settings → Secrets): +# - registry_username: Your Gitea username (used for docker login) +# - registry_password: Gitea container registry password or token # - portainer_webhook_url: Portainer stack webhook URL (Redeploy trigger) # -# Required Environment Variables (Gitea registry): -# - REGISTRY_URL: git.mifi.dev -# - REGISTRY_REPO: git.mifi.dev/mifi-ventures/landing -# - REGISTRY_USERNAME: your Gitea username +# REGISTRY_URL and REGISTRY_REPO are set in this file (above). # # Portainer: Add stack from "Git repository" with this repo, compose path # docker-compose.yml. Enable GitOps → Webhook and "Re-pull image". diff --git a/DEPLOYMENT.md b/DEPLOYMENT.md index 0bf8c56..51b1795 100644 --- a/DEPLOYMENT.md +++ b/DEPLOYMENT.md @@ -26,6 +26,27 @@ This repo includes `docker-compose.yml` for the **Repository** option. The compo - Install Docker on the Linode VPS and run Portainer (e.g. as a container or on the host). - In Portainer, add your **Gitea registry**: **Settings → Registries → Add registry**. Use the same URL and credentials you use for `REGISTRY_*` in Woodpecker so the host can pull `git.mifi.dev/mifi-ventures/landing:latest`. +### 1b. First-time: push the image so the stack can deploy + +Portainer pulls `git.mifi.dev/mifi-ventures/landing:latest`. If that image has never been pushed, you get **manifest unknown**. Push it once (from your machine or by running the Woodpecker pipeline), then create the stack. + +**Option A – Run Woodpecker:** Ensure Woodpecker secrets and variables are set (steps 4–5 below), then push a commit to `main`. The pipeline will build and push the image; after it succeeds, create the stack in Portainer (step 2). + +**Option B – Push from your machine:** + +Use Docker (or OrbStack, Colima, Rancher Desktop) from the repo root. **If you’re on Apple Silicon (M1/M2/M3) or another ARM Mac**, the VPS is x86_64, so build for that platform to avoid “exec format error”: + +```bash +docker login git.mifi.dev # use your Gitea username and token/password +docker buildx build --platform linux/amd64 -t git.mifi.dev/mifi-ventures/landing:latest --push . +``` + +Using `--push` (instead of `--load` then `docker push`) sends the amd64 image straight to the registry and avoids local cache mix-ups. If buildx says “multiple platforms not supported”, run `docker buildx create --name multiarch --use` once, then retry. + +On an x86 Mac or Linux PC you can use `docker build -t ... .` and `docker push` if you prefer. + +Then create the stack in Portainer; the image will exist and the deploy will succeed. + ### 2. Create the Portainer stack **If using Git repository (recommended):** @@ -57,24 +78,17 @@ Use Gitea’s built-in container registry. Image path: ### 4. Configure Woodpecker Secrets -In **Gitea → Repository → Settings → Secrets** (Woodpecker): +Woodpecker has no separate “Variables” UI — add everything under **Repo → Settings → Secrets** in Woodpecker: | Name | Value | |------|-------| +| `registry_username` | Your Gitea username (used for `docker login`) | | `registry_password` | Gitea token or password (package write to the repo’s registry) | | `portainer_webhook_url` | Portainer stack webhook URL (from step 2) | -### 5. Configure Woodpecker Variables +`REGISTRY_URL` and `REGISTRY_REPO` are set in `.woodpecker.yml`; you don’t need to add them anywhere. -In **Gitea → Repository → Settings → Variables** (Woodpecker): - -| Name | Value | -|------|-------| -| `REGISTRY_URL` | `git.mifi.dev` | -| `REGISTRY_REPO` | `git.mifi.dev/mifi-ventures/landing` | -| `REGISTRY_USERNAME` | Your Gitea username | - -### 6. Test Deployment +### 5. Test Deployment #### Local Test Build ```bash @@ -109,7 +123,7 @@ git push origin main # After build + push, deploy step calls Portainer webhook; Portainer redeploys the stack. ``` -### 7. Verify Deployment +### 6. Verify Deployment After the pipeline completes: @@ -159,6 +173,15 @@ networks: - Use a Gitea token with package write permission (or your password if allowed). - Test locally: `echo "TOKEN" | docker login git.mifi.dev -u USERNAME --password-stdin`. +### unauthorized: reqPackageAccess (push rejected after login) +Gitea accepted your login but denied **package** access. Fix: + +1. **Token scope** – Create a Gitea **Personal Access Token** with **Read & Write** (or equivalent) for **Packages**. Use that token as the password for `docker login git.mifi.dev`. +2. **Owner in the image path** – The path is `git.mifi.dev/{owner}/{image}`. The **owner** must be a user or org you can publish packages for: + - If the repo is under org **mifi-ventures**, your user must be a **member** of that org with **Write** (or Admin) so you can create packages under `mifi-ventures`. + - If the repo is under your **user** (e.g. `mifi/landing`), use **your username** as owner: `git.mifi.dev/mifi/landing` (and set `REGISTRY_REPO` to match in Woodpecker and in `docker-compose.yml`). +3. **2FA** – If your account uses 2FA, you must use a token; account password alone may not be enough for package push. + ### Portainer Cannot Pull Image - In Portainer, add the Gitea registry under **Settings → Registries** with the same URL and credentials. - Ensure the stack’s **Re-pull image** (or equivalent) is enabled so redeploys pull the new image. @@ -172,6 +195,25 @@ networks: - Check for port conflicts on the host (e.g. another service using the same port). - Ensure the Gitea registry is added in Portainer so the image can be pulled. +### exec format error (exec /docker-entrypoint.sh) +The container is running an image built for the wrong CPU architecture (e.g. **ARM64** on Apple Silicon vs **AMD64** on Linode). + +1. **Rebuild and push for amd64** (from your Mac, after `docker login git.mifi.dev`): + ```bash + docker buildx build --platform linux/amd64 -t git.mifi.dev/mifi-ventures/landing:latest --push . + ``` + Using `--push` sends the amd64 image straight to the registry. If you see “multiple platforms not supported”, run `docker buildx create --name multiarch --use` once, then retry. + +2. **Force the VPS to pull the new image** — otherwise it may keep using a cached ARM64 copy of `latest`. On the Linode host (SSH): + ```bash + docker rmi git.mifi.dev/mifi-ventures/landing:latest + ``` + Then in Portainer use **Pull and redeploy** (or redeploy with “Re-pull image” enabled) so it pulls the image again. Or redeploy the stack from the Portainer UI after removing the image on the host. + +3. **Confirm the image in the registry is amd64** (optional): after pushing, run `docker buildx imagetools inspect git.mifi.dev/mifi-ventures/landing:latest` — the manifest should list `linux/amd64`. + +Woodpecker runs on amd64, so pipeline-built images are already correct for typical VPS hosts. + ## Rollback Procedure If a bad image was deployed: diff --git a/docker-compose.yml b/docker-compose.yml index 15da113..b19c1a1 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -9,6 +9,12 @@ services: container_name: mifi-ventures-landing pull_policy: always restart: unless-stopped + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"] + interval: 30s + timeout: 3s + start_period: 5s + retries: 3 labels: - "traefik.enable=true" - "traefik.docker.network=marina-net" @@ -17,6 +23,9 @@ services: - "traefik.http.routers.mifiventures.middlewares=secure-all@file,redirect-www-to-non-www@file" - "traefik.http.routers.mifiventures.tls=true" - "traefik.http.routers.mifiventures.tls.certresolver=letsencrypt" + networks: + - marina-net + networks: marina-net: external: true diff --git a/nginx.conf b/nginx.conf index 9a27be1..086d858 100644 --- a/nginx.conf +++ b/nginx.conf @@ -34,8 +34,8 @@ http { gzip_proxied any; gzip_comp_level 6; gzip_min_length 256; + # text/html is always gzipped by default; listing it again causes "duplicate MIME type" warning gzip_types - text/html text/plain text/css text/xml