diff --git a/content/docs/advanced/cli.mdx b/content/docs/advanced/cli.mdx new file mode 100644 index 0000000..c99c112 --- /dev/null +++ b/content/docs/advanced/cli.mdx @@ -0,0 +1,122 @@ +--- +title: CLI Reference +description: Hub command-line interface for backup, restore, and key management +--- + +The Hub binary includes a CLI for administrative tasks that cannot be performed through the web UI. Run any command with `--help` to see all available options. + +When using Docker, prefix commands with `docker compose exec hub /app/hub`: + +```bash +docker compose exec hub /app/hub +``` + + + Commands that ask for a yes/no confirmation (`import`, `key rotate`) don't require `-it`. Without + an attached terminal, the prompt is treated as "no" and the command safely aborts. For scripted or + non-interactive runs, pass `--yes`/`-y` explicitly instead of relying on this behavior. + + +## export + +Creates a consistent backup of the Hub database. The export uses SQLite's `VACUUM INTO` and is safe to run while the Hub is running. + +```bash +hub export [--output ] +``` + +| Flag | Default | Description | +| ---------------- | ------------------------------- | ------------------------------- | +| `-o`, `--output` | `hub-export-YYYYMMDD-HHMMSS.db` | Output path for the backup file | + +**With Docker:** + +```bash +docker compose exec hub /app/hub export +``` + +The file is created inside the container under `/app/data/`. Copy it out of the container to include it in your backup strategy: + +```bash +docker compose cp hub:/app/data/hub-export-*.db ./backups/ +``` + +## import + +Restores a database from a backup file. The existing database is copied to a rollback file before the restore, so you can recover if something goes wrong. + + + The Hub server must be **stopped** before running import. All existing data is overridden by the + backup. + + +```bash +hub import [--yes] +``` + +| Argument / Flag | Description | +| --------------- | ----------------------------- | +| `` | Path to the backup `.db` file | +| `-y`, `--yes` | Skip the confirmation prompt | + +**With Docker:** + +```bash +# Copy the backup into the container +docker compose cp ./backups/hub-export-20240101-120000.db hub:/app/data/ + +# Stop the hub +docker compose stop hub + +# Run import +docker compose run --rm hub /app/hub import data/hub-export-20240101-120000.db + +# Restart the hub +docker compose up -d hub +``` + +## key rotate + +Re-encrypts all sensitive database fields with a new `APP_SECRET`. Use this when you need to rotate your encryption key. + + + The Hub server must be **stopped** before rotating the key. Create a database backup first. If the + rotation fails, restore the backup, keep the old `APP_SECRET`, and retry. + + +```bash +hub key rotate [--old-secret ] [--yes] +``` + +| Flag | Description | +| -------------- | ----------------------------------------------------------------------------- | +| `--old-secret` | Previous `APP_SECRET` value. Can also be set via the `OLD_APP_SECRET` env var | +| `-y`, `--yes` | Skip the confirmation prompt | + +**With Docker:** + +```bash +# 1. Create a backup +docker compose exec hub /app/hub export + +# 2. Stop the hub +docker compose stop hub + +# 3. Rotate the key (set the NEW APP_SECRET in .env first) +docker compose run --rm \ + -e OLD_APP_SECRET= \ + hub /app/hub key rotate --yes + +# 4. Restart the hub with the new APP_SECRET +docker compose up -d hub +``` + +After a successful rotation, all agent tokens and user sessions signed with the old secret are invalidated. Users need to log in again and agents need their tokens re-issued (or simply reconnect. The agent will re-authenticate automatically if the hub is reachable). + +## reset-password + +Resets a user's password and forces them to change it on the next login. See [Account Recovery](/docs/troubleshooting/account-recovery) for full details. + +```bash +hub reset-password +``` diff --git a/content/docs/architecture/agents.mdx b/content/docs/architecture/agents.mdx new file mode 100644 index 0000000..f89ec28 --- /dev/null +++ b/content/docs/architecture/agents.mdx @@ -0,0 +1,74 @@ +--- +title: Agents +description: Managing agents and connecting them to the Hub +--- + +An **Agent** is a lightweight service that runs on the target host where your Docker containers are deployed. It connects to the Hub via WebSocket, receives deployment instructions, and reports status back. You can run multiple agents. One agent per environment, server, or cluster. + +## Creating an Agent + +Before deploying the Agent binary, you need to register it in the Hub to obtain an authentication token. + +1. Navigate to the **Agents** page in the OrcaCD UI. +2. Click **Add Agent** and give it a name (e.g., `production`, `staging`). +3. Copy the generated `AUTH_TOKEN` (only shown once). + +![Create Agent](/assets/docs/create-agent.png?url) + +## Deploying an Agent + +### Same Host as the Hub + +The default `docker-compose.yml` includes both Hub and Agent. If you are running both on the same machine, just set the `AUTH_TOKEN` in your `.env` and restart: + +```bash +docker compose up -d +``` + +### Remote Host + +To deploy an Agent on a separate server, copy only the Agent service definition to that machine. See [installation](/docs/setup/installation) for instructions on how to set up the Agent service. + +The Agent will connect to the Hub. Once connected, its status in the Hub UI changes to **Online**. + + + The Agent needs access to the Docker socket (`/var/run/docker.sock`) to manage containers on the + host. + + +## Multiple Agents + +You can register as many agents as you need. For example, one per environment: + +| Agent name | Purpose | +| ------------ | ----------------------------- | +| `production` | Deploys to the production VPS | +| `staging` | Deploys to a staging server | +| `dev` | Local development environment | + +Each Application in OrcaCD is assigned to exactly one Agent. You can split workloads across agents freely. + +## Rotating an Agent Token + +If a token is compromised or needs to be rotated, navigate to the Agent in the UI, open the options menu, and select **Rotate Token**. A new token is generated immediately and the old token becomes invalid. + +Update the `AUTH_TOKEN` in the Agent's `.env` and restart it: + +```bash +docker compose up -d +``` + +You can also rotate tokens via the API: + +```bash +POST /api/v1/agents/:id/rotate-token +``` + +## Agent Status + +| Status | Meaning | +| --------- | --------------------------------------------------- | +| `online` | Agent is connected and ready to receive deployments | +| `offline` | Agent has disconnected or has not yet connected | + +If an Agent is offline, deployment dispatch fails immediately and the application is marked out-of-sync with an error. Deployments are not queued or retried automatically. Trigger the deployment again once the Agent is back online. diff --git a/content/docs/architecture/applications.mdx b/content/docs/architecture/applications.mdx new file mode 100644 index 0000000..c8b9b29 --- /dev/null +++ b/content/docs/architecture/applications.mdx @@ -0,0 +1,89 @@ +--- +title: Applications +description: Creating and managing applications in OrcaCD +--- + +An **Application** in OrcaCD represents a Docker Compose deployment. It links a repository (and a specific branch and file path) to an Agent, which runs the actual containers. + +## Creating an Application + +1. Navigate to the **Applications** page and click **Add Application**. +2. Fill in the required fields: + + | Field | Description | + | -------------- | ---------------------------------------------------------------------------------------------- | + | **Name** | Display name for the application | + | **Repository** | The repository containing the Compose file | + | **Branch** | The branch to track (e.g., `main`, `production`) | + | **Path** | Path to the `docker-compose.yml` inside the repository (e.g., `apps/myapp/docker-compose.yml`) | + | **Agent** | The agent that will execute the deployment | + +3. Click **Create**. + +OrcaCD will immediately sync the repository and deploy the Compose file to the selected Agent. + +## Application Status + +Each application shows two status indicators: + +### Sync Status + +| Status | Meaning | +| ------------- | ---------------------------------------------------- | +| `Synced` | Deployed commit matches the latest repository commit | +| `Out Of Sync` | A new commit exists that has not been deployed yet | +| `Syncing` | A deployment is currently in progress | +| `Unknown` | No deployment has been triggered yet | + +### Health Status + +| Status | Meaning | +| ----------- | ---------------------------------------------------- | +| `Healthy` | All containers from the Compose file are running | +| `Unhealthy` | One or more containers are stopped or in a bad state | +| `Unknown` | Health has not been checked yet | + +## Triggering a Deployment + +OrcaCD automatically deploys when the tracked repository branch receives a new commit (depending on the repository sync strategy). You can also trigger a deployment manually: + +1. Open the application. +2. Click **Deploy** in the top-right corner. + +This forces an immediate sync and deployment regardless of the current sync status. + +## Application Settings + +Open an application and navigate to the **Settings** tab to configure it. + +### General + +Change the application name, icon, linked repository, branch, path, or agent. + +### Image Polling + +Image polling lets OrcaCD automatically pull updated Docker images and restart containers, even when no Compose file has changed. This is useful for continuous delivery workflows where a CI pipeline pushes new image tags. + +| Setting | Description | +| ------------------------ | ---------------------------------------------------------------------------- | +| **Enable image polling** | Turns image polling on or off | +| **Polling interval** | How often to check for new images (minimum 30 seconds, default 120 seconds) | +| **Delete old images** | When enabled, old images are removed from the host after a successful update | + +## Image Pull Webhooks + +Instead of polling, you can trigger an image pull from your container registry via a webhook. This is ideal for registry-side push notifications. + +1. Open the application settings. +2. In the **Image Pull Webhook** section, click **Generate Webhook**. +3. OrcaCD returns a webhook URL and secret. +4. Register this webhook in your container registry (e.g., Docker Hub, GitHub Container Registry, Harbor). + +When the registry sends a push event to the webhook URL, OrcaCD instructs the Agent to pull the latest image and restart the affected container. + + + The Agent must be online for the image pull webhook to succeed. If the Agent is offline, the event + is not queued. + + +To revoke a webhook and generate a new one, click **Revoke Webhook** and then **Generate Webhook** again. diff --git a/content/docs/architecture.mdx b/content/docs/architecture/index.mdx similarity index 99% rename from content/docs/architecture.mdx rename to content/docs/architecture/index.mdx index 44831cc..c111564 100644 --- a/content/docs/architecture.mdx +++ b/content/docs/architecture/index.mdx @@ -1,5 +1,5 @@ --- -title: Architecture +title: Overview description: An overview of the architecture of OrcaCD. --- diff --git a/content/docs/architecture/notifications.mdx b/content/docs/architecture/notifications.mdx new file mode 100644 index 0000000..e384de8 --- /dev/null +++ b/content/docs/architecture/notifications.mdx @@ -0,0 +1,106 @@ +--- +title: Notifications +description: Setting up deployment notifications in OrcaCD +--- + +OrcaCD can send notifications when a deployment succeeds or fails. Notifications can be scoped to specific applications or applied globally. + +## Supported Providers + +- Discord +- Gotify +- Slack +- Email (SMTP) +- Microsoft Teams +- Generic Webhook +- Custom (Shoutrrr) + +## Creating a Notification + +1. Navigate to **Notifications** and click **Add Notification**. +2. Choose a provider type and enter a name. +3. Fill in the provider-specific configuration (see below). +4. Optionally link the notification to specific applications. +5. Save. + +Use the **Test** button to send a test message and verify that the configuration is correct. + +## Provider Configuration + +### Discord + +Fill in these fields in the notification form: + +| Field | Required | Description | +| --------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------- | +| **Webhook URL** | yes | Full webhook URL, copied from your Discord server under **Server Settings → Integrations → Webhooks → (select webhook) → Copy Webhook URL** | +| **Bot Name** | no | Override the bot display name | +| **Avatar URL** | no | Override the bot avatar URL | +| **Thread ID** | no | Send to a specific thread | + +### Gotify + +| Field | Required | Description | +| --------------- | -------- | ---------------------------------------------------------- | +| **Server URL** | yes | Full URL of your Gotify instance (http or https) | +| **App Token** | yes | Application token, created in the Gotify UI under **Apps** | +| **Priority** | yes | Message priority, between -2 and 10 (suggested default: 5) | +| **Custom Path** | no | Custom path prefix if Gotify is behind a sub-path proxy | + +### Slack + +| Field | Required | Description | +| --------------- | -------- | --------------------------------------------------------------------------------------------------------------------- | +| **Webhook URL** | yes | Create an [Incoming Webhook](https://api.slack.com/messaging/webhooks) in your Slack workspace and paste its URL here | + +### Email (SMTP) + +| Field | Required | Description | +| ---------------- | -------- | ----------------------------------------------- | +| **SMTP Host** | yes | SMTP server hostname (no scheme or port) | +| **SMTP Port** | yes | SMTP port (e.g., 587 for STARTTLS, 465 for TLS) | +| **From Address** | yes | Sender email address | +| **To Addresses** | yes | Recipient email addresses, one per line | +| **Username** | no | SMTP authentication username | +| **Password** | no | SMTP authentication password | +| **From Name** | no | Sender display name | +| **Use TLS** | no | Use STARTTLS (default: on) | + +### Microsoft Teams + +| Field | Required | Description | +| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Webhook URL** | yes | Create an [Incoming Webhook connector](https://learn.microsoft.com/en-us/microsoftteams/platform/webhooks-and-connectors/how-to/add-incoming-webhook) in your Teams channel and paste its URL here | +| **Title** | no | Custom message title | + +### Generic Webhook + +Sends a JSON POST request to any HTTP/HTTPS endpoint. + +| Field | Required | Description | +| --------------- | -------- | --------------------------------------------------------------------- | +| **Webhook URL** | yes | Target URL (http or https) | +| **Headers** | no | Additional HTTP request headers, one per line as `Header-Name: value` | + +### Custom (Shoutrrr) + +For any service supported by [Shoutrrr](https://containrrr.dev/shoutrrr/) that doesn't have a dedicated provider, enter the raw Shoutrrr URL directly. + +``` +pushover://token@user +ntfy://topic@ntfy.sh +``` + +Refer to the [Shoutrrr documentation](https://containrrr.dev/shoutrrr/services/overview/) for the URL format of each service. + +## Notification Scope + +### Enable by Default + +When **Enable by Default** is on, the notification is sent for all applications. Including ones created in the future, unless explicitly unlinked. + +### Per-Application + +When **Enable by Default** is off, the notification is only sent for the applications listed in the **Applications** field. + +You can mix both approaches: use "enable by default" for a global notification channel, and add separate per-application notifications for channels that should only receive specific alerts. diff --git a/content/docs/architecture/repositories.mdx b/content/docs/architecture/repositories.mdx new file mode 100644 index 0000000..d5bd777 --- /dev/null +++ b/content/docs/architecture/repositories.mdx @@ -0,0 +1,91 @@ +--- +title: Repositories +description: Connecting and managing Git repositories in OrcaCD +--- + +A **Repository** in OrcaCD is a Git repository that contains Docker Compose files. OrcaCD keeps the repository in sync with its remote and uses it as the source of truth for your deployments. + +## Supported Providers + +- GitHub +- GitLab +- Gitea +- Azure DevOps +- Bitbucket +- Generic (Git) + +## Adding a Repository + +1. Navigate to the **Repositories** page and click **Add Repository**. +2. Enter the repository URL (e.g., `https://github.com/your-org/your-repo`). +3. Select the provider. +4. Choose an authentication method. +5. Choose a sync strategy. +6. Save. + +OrcaCD will immediately attempt to clone the repository and perform an initial sync. + +## Authentication Methods + +### None + +For public repositories, no credentials are required **but recommended** for security. + +### Token (HTTPS) + +Use a personal access token or deploy token. Enter the token in the **Auth Token** field. + +For GitHub, create a [fine-grained personal access token](https://github.com/settings/tokens) with read access to **Contents**. + +For GitLab, create a [project access token](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) with `read_repository` scope. + +## Sync Strategies + +### Polling + +OrcaCD periodically checks the remote repository for new commits. The minimum polling interval is **30 seconds**; the default is **60 seconds**. + +Use polling when: + +- You cannot expose an inbound webhook endpoint +- You want a simple setup without additional configuration + +### Webhook + +OrcaCD listens for push events from your Git provider via webhook. This is more efficient than polling and reacts to new commits instantly. + +#### Setting Up a Webhook + +1. Add the repository with sync type **Webhook**. +2. After saving, open the repository settings. A webhook URL and secret should be generated. +3. Register this webhook in your Git provider: + + **GitHub:** Settings → Webhooks → Add webhook + - Payload URL: `https://your-hub-url/api/v1/webhooks/repositories/` + - Content type: `application/json` + - Secret: copy from OrcaCD + - Events: **Just the push event** + + **GitLab:** Settings → Webhooks + - URL: `https://your-hub-url/api/v1/webhooks/repositories/` + - Secret token: copy from OrcaCD + - Trigger: **Push events** + +### Manual + +The repository is only synced when you explicitly trigger a sync from the UI or API. + +## GitHub Actions OIDC + +For GitHub repositories, you can enable **GitHub Actions OIDC** integration. This allows GitHub Actions workflows to trigger deployments directly without storing a long-lived token in your CI secrets. + +See the [GitHub Actions guide](/docs/guides/github-actions) for details. + +## Repository Status + +| Status | Meaning | +| --------- | ---------------------------------- | +| `success` | Last sync completed without errors | +| `syncing` | Sync is in progress | +| `failed` | Last sync failed | +| `unknown` | Repository has not been synced yet | diff --git a/content/docs/brand.mdx b/content/docs/brand.mdx index 58a3113..06345eb 100644 --- a/content/docs/brand.mdx +++ b/content/docs/brand.mdx @@ -3,8 +3,99 @@ title: Brand description: Brand guidelines for OrcaCD, including logo usage, color palette, typography, and more. --- -TODO: Add brand guidelines, including logo usage, color palette, typography, and more. +This page collects the visual identity of OrcaCD. The logo, color palette, and typography used across +the app, the marketing site, and this documentation. Use these assets and values when referring to +OrcaCD in blog posts, talks, integrations, or third-party tooling. + +## Name & tagline + +- **Name**: OrcaCD (written as one word, capital "O" and "CD") +- **Tagline**: Simple GitOps for Docker +- **One-liner**: OrcaCD is a simple GitOps tool for Docker that lets you deploy applications using Git as the source of truth. ## Logo +The OrcaCD logo is an orca mark on a rounded, colored tile. It is available as a scalable SVG and as +pre-rendered PNGs in several fixed sizes for places that don't support SVG (favicons, app manifests, etc.). + ![Logo](/assets/logo-dark-256.png?url) + +### Available files + +| Asset | Path | Notes | +| ----------------- | ------------------------------ | ----------------------------------------------------------------------------------- | +| Vector logo (SVG) | `/assets/logo-dark.svg` | Preferred format, scales to any size | +| PNG raster | `/assets/logo-dark-{size}.png` | `size` is one of `32`, `64`, `96`, `128`, `144`, `180`, `192`, `256`, `512`, `1024` | +| Favicon | `/assets/favicon.ico` | Multi-resolution ICO (16×16, 32×32) | +| Apple touch icon | `/assets/apple-touch-icon.png` | Used for iOS home screen bookmarks | + +Additional source variants exist (a borderless version and a plain black/white orca mark without the +background tile) for cases where the default dark tile doesn't fit. Reach out to the maintainers if you +need one of these for an official use case. + +### Usage guidelines + +- Do not recolor, recreate, or distort the logo. Use the provided files as-is. +- Keep clear space around the logo roughly equal to the height of the orca mark itself. Don't crowd + it with other text or UI elements. +- Prefer the SVG wherever possible; fall back to the closest matching PNG size only when SVG isn't supported. +- The current logo only ships in a dark-tile variant. If you need a version for a dark background, use + the borderless or plain-mark source files rather than placing the default tile on a matching dark background. + +## Color palette + +OrcaCD's UI is built with Tailwind CSS and [shadcn/ui](https://ui.shadcn.com/), with colors defined as +CSS variables in [`oklch()`](https://oklch.com/) notation so the palette stays perceptually consistent +between light and dark mode. The brand color is a blue at hue `242` (light mode) / `237` (dark mode). + +### Brand color + +| Token | Light mode | Dark mode | Approx. hex | +| ------------------------ | ---------------------- | ---------------------- | ------------------------------------ | +| `--primary` / `--accent` | `oklch(0.59 0.14 242)` | `oklch(0.68 0.15 237)` | `#0186c8` (light) / `#00a4e8` (dark) | +| `--primary-foreground` | `oklch(0.98 0.01 237)` | `oklch(0.985 0 0)` | near white | + +### Base colors + +| Token | Light mode | Dark mode | +| --------------- | ----------------------------------- | ---------------------------- | +| `--background` | `oklch(1 0 0)` | `hsl(0, 0%, 11%)` | +| `--foreground` | `oklch(0.145 0 0)` | `oklch(0.985 0 0)` | +| `--card` | `oklch(1 0 0)` | `oklch(0.205 0 0)` | +| `--secondary` | `oklch(0.967 0.001 286.375)` | `oklch(0.274 0.006 286.033)` | +| `--muted` | `oklch(0.97 0 0)` | `oklch(0.269 0 0)` | +| `--border` | `oklch(0.922 0 0)` | `oklch(1 0 0 / 10%)` | +| `--destructive` | `oklch(0.58 0.22 27)` (`≈ #df2225`) | `oklch(0.704 0.191 22.216)` | + +### Chart / data-visualization gradient + +A five-step gradient built around the brand blue, used for charts and other data visualizations: + +| `--chart-1` | `--chart-2` | `--chart-3` | `--chart-4` (= brand blue) | `--chart-5` | +| ---------------------- | ---------------------- | ---------------------- | -------------------------- | ---------------------- | +| `oklch(0.83 0.10 230)` | `oklch(0.75 0.14 233)` | `oklch(0.68 0.15 237)` | `oklch(0.59 0.14 242)` | `oklch(0.50 0.12 243)` | + + + Dark mode is applied via a `.dark` class on the `` element. Colors get a slightly higher + lightness in dark mode (e.g. the brand blue goes from `L 0.59` to `L 0.68`) to stay readable against + the dark background. + + +## Typography + +OrcaCD uses a single typeface everywhere. **[Geist Mono Variable](https://vercel.com/font)**, a +monospace variable font for both UI text and body copy. There is no secondary sans-serif font; the +monospace look is a deliberate part of the brand identity. + +```css +--font-mono: "Geist Mono Variable", monospace; +``` + +The font is loaded via the [`@fontsource-variable/geist-mono`](https://fontsource.org/fonts/geist-mono) npm +package and applied to both `` and `` through the `font-mono` utility class. + +## Shape language + +Rounded corners are used consistently across the UI, based on a single `--radius` value (`0.625rem`) +that scales up and down for different component sizes (`sm`, `md`, `lg`, `xl`, `2xl`, `3xl`, `4xl`). +Keep this scale when designing new components or marketing assets so they feel consistent with the app. diff --git a/content/docs/guides/github-actions.mdx b/content/docs/guides/github-actions.mdx new file mode 100644 index 0000000..db247ab --- /dev/null +++ b/content/docs/guides/github-actions.mdx @@ -0,0 +1,49 @@ +--- +title: GitHub Actions +description: Trigger OrcaCD deployments from GitHub Actions using OIDC +--- + +OrcaCD supports triggering deployments directly from GitHub Actions using [GitHub's OIDC tokens](https://docs.github.com/en/actions/security-for-github-actions/security-hardening-your-deployments/about-security-hardening-with-openid-connect). This means you don't need to store any long-lived credentials in your repository secrets. The identity of the workflow is verified cryptographically. + +## Prerequisites + +- A GitHub repository connected in OrcaCD with provider type **GitHub** +- **GitHub Actions OIDC** enabled on that repository in OrcaCD (Repository Settings → enable the toggle) +- The OrcaCD Hub must be reachable from GitHub's network + +## How It Works + +When a GitHub Actions workflow runs, it requests a short-lived OIDC token from GitHub. OrcaCD verifies this token against GitHub's public OIDC endpoint and checks that: + +1. The token's repository claim matches a GitHub repository registered in OrcaCD with GitHub Actions OIDC enabled. +2. The workflow was **not** triggered by a `pull_request` or `pull_request_target` event (to prevent untrusted forks from triggering deployments). + +If verification succeeds, OrcaCD finds all applications linked to the matching repository and branch, then dispatches the requested actions. + +## Example Workflow + +Add a step at the end of your CI workflow to notify OrcaCD after a successful build or image push: + +```yaml +permissions: + id-token: write + +- uses: OrcaCD/deploy-action@... + with: + # The OrcaCD hub URL (e.g., https://orca.example.com) + # Required + hub: https://orca.example.com + + # Whether to sync the repo content (compose files) + # Optional, default: true + syncRepo: true + + # Whether to pull the latest container image versions + # Optional, default: false + pullImages: false +``` + +## Branch and Tag Support + +- **Branch pushes**: OrcaCD deploys all applications linked to the pushed branch. +- **Tag pushes**: OrcaCD resolves which branches the tagged commit belongs to and deploys all applications linked to those branches. diff --git a/content/docs/index.mdx b/content/docs/index.mdx index 0a7d635..74b02c5 100644 --- a/content/docs/index.mdx +++ b/content/docs/index.mdx @@ -40,8 +40,6 @@ import { HomeIcon } from "lucide-react"; [Try the OrcaCD Demo](/docs/demo) -TODO: demo image or gif here - ## Useful Links - [Installation](/docs/setup/installation) diff --git a/content/docs/meta.json b/content/docs/meta.json index 6d9ba31..73d9049 100644 --- a/content/docs/meta.json +++ b/content/docs/meta.json @@ -6,13 +6,14 @@ "---Getting Started---", "index", "demo", - "architecture", "---[Rocket]Setup---", "...setup", "---[Settings]Configuration---", "...configuration", "---[Book]Guides---", "...guides", + "---[PencilRuler]Architecture---", + "...architecture", "---[Pickaxe]Advanced---", "...advanced", "---[Bug]Troubleshooting---", diff --git a/content/docs/troubleshooting/common-issues.mdx b/content/docs/troubleshooting/common-issues.mdx index 1726a4a..e43a382 100644 --- a/content/docs/troubleshooting/common-issues.mdx +++ b/content/docs/troubleshooting/common-issues.mdx @@ -3,4 +3,62 @@ title: Common Issues description: Solutions to frequently encountered problems --- -No issues have been documented yet. If you encounter a problem, please report it in the [GitHub Issues](https://github.com/OrcaCD/orca-cd/issues/new?template=bug.yml) and we will investigate it as soon as possible. +## Agent stays Offline after connecting + +**Symptoms:** The Agent is running but shows as **Offline** in the Hub UI. + +**Checks:** + +1. Verify `HUB_URL` in the Agent's `.env` is correct and reachable from the Agent's host. +2. Confirm the `AUTH_TOKEN` matches the token generated for that Agent in the Hub UI. +3. Check Agent logs: `docker compose logs agent` and look for connection errors. +4. If the Hub is behind a reverse proxy, make sure WebSocket upgrades are forwarded correctly. See the [Reverse Proxy guide](/docs/guides/reverse-proxy). + +## Hub is not accessible / returns 502 + +**Checks:** + +1. Confirm the Hub container is running: `docker compose ps` +2. Check Hub logs: `docker compose logs hub` +3. Verify your reverse proxy is forwarding to the correct port (default: `8080`). +4. If you set `TRUSTED_PROXIES`, confirm the proxy's IP is included. An incorrect value can cause the Hub to reject requests. + +## Deployment is stuck in "Syncing" + +**Symptoms:** An application stays in the `syncing` state indefinitely. + +**Checks:** + +1. Verify the Agent is online. +2. Check Agent logs for errors during the Docker Compose up/pull step. +3. Ensure the Agent has access to the Docker socket (`/var/run/docker.sock`). +4. If the Compose file references private images, confirm the Agent host has credentials to pull them (e.g., `docker login` was run on that host). + +## Repository sync fails with authentication error + +**Symptoms:** Sync status shows `failed` with an authentication error. + +**Checks:** + +1. Confirm the auth token is still valid and has not expired or been revoked. +2. For token auth, verify the token has `read_repository` (GitLab) or `Contents: read` (GitHub) permissions. +3. Use the **Test Connection** button in the repository settings to check credentials without triggering a full sync. + +## Webhook sync not triggering + +**Symptoms:** Pushes to the repository do not trigger a sync. + +**Checks:** + +1. Confirm the webhook URL and secret in your Git provider match what OrcaCD shows in the repository settings. +2. Check that the Hub is publicly reachable on the configured `APP_URL`. +3. Review the webhook delivery logs in your Git provider (GitHub: Settings → Webhooks → Recent Deliveries) to see if the request reached the Hub. +4. Verify the webhook is configured to send **push** events. + +## Cannot log in after enabling OIDC / disabling local auth + +If you locked yourself out by disabling local authentication, see [Account Recovery](/docs/troubleshooting/account-recovery). + +--- + +If your issue is not listed here, please report it in [GitHub Issues](https://github.com/OrcaCD/orca-cd/issues/new?template=bug.yml). diff --git a/package.json b/package.json index 5f0b91d..c811b92 100644 --- a/package.json +++ b/package.json @@ -21,11 +21,11 @@ "@tanstack/start-static-server-functions": "1.167.17", "clsx": "^2.1.1", "fumadocs-core": "16.10.5", - "fumadocs-mdx": "15.0.12", + "fumadocs-mdx": "15.0.13", "fumadocs-ui": "16.10.5", "lucide-react": "^1.21.0", "lucide-static": "^1.21.0", - "motion": "^12.41.0", + "motion": "^12.42.0", "react": "^19.2.7", "react-dom": "^19.2.7", "swr": "^2.4.2", @@ -45,5 +45,5 @@ "tailwindcss": "^4.3.1", "typescript": "^6.0.3" }, - "packageManager": "pnpm@11.2.1" + "packageManager": "pnpm@11.9.0" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a43992..ebeb47a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -30,8 +30,8 @@ importers: specifier: 16.10.5 version: 16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3) fumadocs-mdx: - specifier: 15.0.12 - version: 15.0.12(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3))(react@19.2.7)(rolldown@1.1.3)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(jiti@2.7.0)) + specifier: 15.0.13 + version: 15.0.13(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3))(react@19.2.7)(rolldown@1.1.3)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(jiti@2.7.0)) fumadocs-ui: specifier: 16.10.5 version: 16.10.5(@tailwindcss/oxide@4.3.1)(@types/mdx@2.0.14)(@types/react-dom@19.2.3(@types/react@19.2.17))(@types/react@19.2.17)(fumadocs-core@16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(tailwindcss@4.3.1) @@ -42,8 +42,8 @@ importers: specifier: ^1.21.0 version: 1.21.0 motion: - specifier: ^12.41.0 - version: 12.41.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + specifier: ^12.42.0 + version: 12.42.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: specifier: ^19.2.7 version: 19.2.7 @@ -1764,8 +1764,8 @@ packages: zod: optional: true - fumadocs-mdx@15.0.12: - resolution: {integrity: sha512-R4WenrNQxSKi+QU46Q1cscVWi+S90dj3As4jdN+vgChO2o0TVOj+FFIe3onWM7mglhPj53NxZp/upP+t/ryekQ==} + fumadocs-mdx@15.0.13: + resolution: {integrity: sha512-VsGhCiLriXXMzm3WbgrVP7t6LvOthwh1BC+IGSI1ZW63UcSo1jE4aAiuUrTIF0jv1EGQkJG8cPsy0cOnf4sejA==} hasBin: true peerDependencies: '@types/mdast': '*' @@ -1908,6 +1908,10 @@ packages: resolution: {integrity: sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==} hasBin: true + js-yaml@5.2.0: + resolution: {integrity: sha512-YeLUMlvR4Ou1B119LIaM0r65JvbOBooJDc9yEu0dClb/uSC5P4FrLU8OCCz/HXWvtPoIrR0dRzABTjo1sTN9Bw==} + hasBin: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -2175,8 +2179,8 @@ packages: motion-utils@12.39.0: resolution: {integrity: sha512-8nadJAJjTtqRkmRF36FoJTrywK9nnFmnPwnSMyxaOCU7GDjN9RTMJIxx9De8ErM+vpPhMccr/6fo5WciyQLnMQ==} - motion@12.41.0: - resolution: {integrity: sha512-avEDKE22rFPJqDr3Ttk7gMQpeaOmNik60NoJ5T0tj+RBCNvz21D3ArY3l4uitoeQ7eIpDqueWaO3pPYFv8JOVA==} + motion@12.42.0: + resolution: {integrity: sha512-Qhwvu9sVl5/URSq5CNzwMCpSKK8Uhnrwb6VO977kZyj/wOCS7mWebJUnBoHx5cZU1Zv8a9BD5CSICWKAlrLJgA==} peerDependencies: '@emotion/is-prop-valid': '*' react: ^18.0.0 || ^19.0.0 @@ -4062,7 +4066,7 @@ snapshots: transitivePeerDependencies: - supports-color - fumadocs-mdx@15.0.12(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3))(react@19.2.7)(rolldown@1.1.3)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(jiti@2.7.0)): + fumadocs-mdx@15.0.13(@types/mdast@4.0.4)(@types/mdx@2.0.14)(@types/react@19.2.17)(fumadocs-core@16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3))(react@19.2.7)(rolldown@1.1.3)(vite@8.1.0(@types/node@26.0.1)(esbuild@0.28.1)(jiti@2.7.0)): dependencies: '@mdx-js/mdx': 3.1.1 '@standard-schema/spec': 1.1.0 @@ -4070,7 +4074,7 @@ snapshots: esbuild: 0.28.1 estree-util-value-to-estree: 3.5.0 fumadocs-core: 16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3) - js-yaml: 4.2.0 + js-yaml: 5.2.0 mdast-util-mdx: 3.0.0 picocolors: 1.1.1 picomatch: 4.0.4 @@ -4108,7 +4112,7 @@ snapshots: class-variance-authority: 0.7.1 fumadocs-core: 16.10.5(@mdx-js/mdx@3.1.1)(@tanstack/react-router@1.170.16(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(@types/estree-jsx@1.0.5)(@types/hast@3.0.4)(@types/mdast@4.0.4)(@types/react@19.2.17)(lucide-react@1.21.0(react@19.2.7))(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(zod@4.4.3) lucide-react: 1.21.0(react@19.2.7) - motion: 12.41.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + motion: 12.42.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) next-themes: 0.4.6(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react: 19.2.7 react-dom: 19.2.7(react@19.2.7) @@ -4279,6 +4283,10 @@ snapshots: dependencies: argparse: 2.0.1 + js-yaml@5.2.0: + dependencies: + argparse: 2.0.1 + jsesc@3.1.0: {} json5@2.2.3: {} @@ -4785,7 +4793,7 @@ snapshots: motion-utils@12.39.0: {} - motion@12.41.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): + motion@12.42.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: framer-motion: 12.42.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) tslib: 2.8.1