diff --git a/AGENTS.md b/AGENTS.md index 8884da2..4218aa5 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -50,7 +50,7 @@ A repository-specific exception must be declared through the `skip` input of ## Repository Overview -This is a Docker-based application management system (flightdeck) that orchestrates core self-hosted services using docker-compose. The architecture uses Traefik as a reverse proxy with automatic SSL certificate management, and can merge optional extra application catalogs during deploy. There is no manual administration flow at all - no server-side console access, no local quick-start. Every deploy goes through `targets/`/`vaults/` manifests and GitHub Actions (`deploy/deploy.py`); see the "Environment Variable System" and "CI/CD" sections below. +This is a Docker-based deployment system (flightdeck) that manages core services via docker-compose. The architecture uses Traefik as a reverse proxy with automatic SSL certificate management, and can merge optional extra application catalogs during deploy. There is no manual administration flow at all - no server-side console access, no local quick-start. Every deploy goes through `targets/`/`vaults/` manifests and GitHub Actions (`deploy/deploy.py`); see the "Environment Variable System" and "CI/CD" sections below. ## Core Architecture @@ -342,11 +342,11 @@ Deployment helpers live in this repository, entirely under `deploy/`, run only o - `.github/actions/encrypt-env/` is a local composite action for rendering `vaults/` manifests from GitHub Secrets/Variables, encrypting them for age recipients, and publishing `.sops.env` as a GitHub Release asset — vault manifests hold only env/secrets, not app selection - `.github/workflows/deploy-shared.yml` is a reusable workflow consumer repos call to run `deploy/deploy.py` from GitHub Actions over an optional Tailscale connection, without holding any deploy secrets in this repository -The `releases/{timestamp}`/`current` symlink pattern (Capistrano-style) exists for atomicity, not for rollback: a deploy either fully lands and only then switches the symlink as its last step, or fails partway and leaves `current` untouched — never a partially-applied app. There is deliberately no automated rollback, and manual rollback (point `current` at an old release directory by hand) is not a supported/maintained path — it wouldn't restore that release's rendered config templates (`apps-data/{app}/config/` isn't versioned per release) or a floating-tag image's historical version either, and in practice fixing forward through the normal deploy path is simpler and safer than reasoning about what a partial rollback actually restores. +The `releases/{timestamp}`/`current` symlink pattern exists for atomicity, not for rollback: a deploy either fully lands and only then switches the symlink as its last step, or fails partway and leaves `current` untouched — never a partially-applied app. There is deliberately no automated rollback, and manual rollback (point `current` at an old release directory by hand) is not a supported/maintained path — it wouldn't restore that release's rendered config templates (`apps-data/{app}/config/` isn't versioned per release) or a floating-tag image's historical version either, and in practice fixing forward through the normal deploy path is simpler and safer than reasoning about what a partial rollback actually restores. App bundles listed in `app_refs` are release assets referenced as short refs like `/@latest` or `/@v1.2.3`, resolving to a default asset name of `flightdeck-apps.zip` unless the ref specifies an explicit `:asset-name` suffix. `@latest` is resolved through GitHub's latest release API. Every bundle must contain an `apps/` directory; both per-app directories and shared top-level files (`common.yml`, `networks.yml`, etc.) merge the same way — copy if new, fail loud on any name conflict across bundles. -Each app in a target's `apps` mapping lists its own `env_refs` — release refs the same shape as app bundles, with no default asset name (every entry must specify an explicit `:asset-name` suffix, since there's no single obvious default under a per-app model). `deploy/deploy.py` downloads them still encrypted and checks for key collisions from the ciphertext (SOPS's dotenv output only encrypts values, so key names are readable without decryption) — scoped to that one app's own sources, not across apps, since each app ends up with its own separate `.env`. Decryption itself happens on the runner too, using the target's private age key (`credentials.secrets.sops_age_key`, a GitHub Secret) - the target host never holds this key and never runs `sops`. `apps` moved off the vault schema onto the target, and vaults moved from one-per-target to one-per-app, so that a vault can declare its output env var names directly (`HTTP_PORT`, not `TRAEFIK_HTTP_PORT`) without an implicit prefix-strip happening anywhere between the vault and the app's `.env`. +Each app in a target's `apps` mapping lists its own `env_refs` — release refs the same shape as app bundles, with no default asset name (every entry must specify an explicit `:asset-name` suffix, since there's no single obvious default under a per-app model). See "Environment Variable System" above for how these get resolved, checked for collisions, and decrypted. ## Notable App Configurations diff --git a/README.md b/README.md index 5f4a9da..c6b70f6 100644 --- a/README.md +++ b/README.md @@ -1,30 +1,25 @@ -# Flightdeck - Core Self-Hosted Application Runtime +# Flightdeck - Docker Compose Deployment System -A Docker-based orchestration system for deploying core self-hosted services, with optional extra application catalogs. Built with Traefik reverse proxy, automatic SSL certificate management, and GitHub Actions-driven deployment. +A Docker-based deployment system for containerized services, with optional extra application catalogs. No manual administration — every deploy is push-based, resolved and applied entirely from GitHub Actions. Built with Traefik reverse proxy and automatic SSL certificate management. ## 🎯 Key Features - **Core Application Set** - Essential services for routing, auth, monitoring, automation, database access, error tracking, and analytics -- **Extra Application Bundles** - Optional release app catalogs can be merged during deploy -- **Traefik Reverse Proxy** - Automatic routing, SSL/TLS termination, and certificate management -- **Automatic SSL Certificates** - Support for Cloudflare DNS and Let's Encrypt HTTP challenges -- **Modular Architecture** - Reusable docker-compose components for easy maintenance and scaling +- **Automatic SSL Certificates** - Cloudflare DNS and Let's Encrypt HTTP challenge support, routed through Traefik +- **Modular Architecture** - Reusable docker-compose components for easy maintenance - **Vault-based Configuration** - Each app's env is declared, encrypted, decrypted, and rendered per app - no server-side secrets handling - **Persistent Data Management** - Organized storage with automatic backup-friendly structure - **Database Integration** - PostgreSQL, Redis, MongoDB, TimescaleDB pre-configured - **Health Checks** - Built-in health monitoring for all services -- **Push-based Deploy** - GitHub Actions resolves, decrypts, and renders everything on the runner, then pushes a finished result over SSH ## 📋 Target Server Requirements -There is no manual administration flow - target servers are never logged into to run commands, and there is no local quick-start. Every deploy goes through target/vault manifests and GitHub Actions. A target server needs only: +A target server needs only: - **Docker** >= 20.10 - **Docker Compose** >= 2.0 - SSH access for the deploy key configured in that target's `credentials` -Nothing else - no `sops`, no age key, no `gh`, no flightdeck scripts of any kind. All of that runs on the GitHub Actions runner instead; see "Automated Deploy" below. - ## 🚀 Automated Deploy Deployment goes through [`deploy-shared.yml`](.github/workflows/deploy-shared.yml) (documented in the GitHub Actions section below), a reusable workflow wrapping [`deploy/deploy.py`](deploy/deploy.py) behind plain deploy vocabulary — `hosts`, `app-refs`, `apps`. @@ -118,9 +113,8 @@ To use the override for a given deploy, that app's own vault sets `MYAPP_SOME_PA - **traefik** - External network for reverse proxy communication - **internal** - Isolated network for app-to-app communication - **databases** - Dedicated network for database services (PostgreSQL, Redis, MongoDB) -- **mcp** - External network for MCP services consumed by MetaMCP -`traefik`, `databases`, and `mcp` are created on the target host by `deploy/deploy.py` (derived from `apps/networks.yml`'s `external: true` entries); `internal` is created by Docker Compose itself. +`traefik` and `databases` are created on the target host by `deploy/deploy.py` (derived from `apps/networks.yml`'s `external: true` entries); `internal` is created by Docker Compose itself. ## 🆕 Adding a New Application @@ -186,14 +180,12 @@ A few things that don't fit that one-liner: ## 🔄 Similar Services -If you're evaluating alternatives, these projects solve a similar problem from different angles: +Useful as a source of ready-made Docker Compose definitions when adding a new app to this catalog, or as a reference for how to structure one: -| Service | Website | Focus | Service Templates | -|------|---------|---------|---------| -| **flightdeck** | This repository | Git-based Docker Compose stack with reusable templates, deployed via GitHub Actions | [apps](./apps/) | -| **Dokploy** | [dokploy.com](https://dokploy.com) | PaaS-style deployment panel for apps, databases, and containers | [Dokploy/templates/blueprints](https://github.com/Dokploy/templates/tree/canary/blueprints) | -| **Runtipi** | [runtipi.io](https://runtipi.io) | Beginner-friendly self-hosted app store and dashboard | [runtipi/runtipi-appstore/apps](https://github.com/runtipi/runtipi-appstore/tree/master/apps) | -| **Coolify** | [coolify.io](https://coolify.io) | Self-hosted Heroku/Vercel-style platform for apps, databases, and services | [coollabsio/coolify/templates/compose](https://github.com/coollabsio/coolify/tree/v4.x/templates/compose) | +- [Dokploy](https://dokploy.com) +- [Runtipi](https://runtipi.io) +- [Coolify](https://coolify.io) +- [Portainer](https://www.portainer.io) ## ⚙️ GitHub Actions @@ -372,4 +364,4 @@ The `@v1.2.3` pin on the `uses:` line only controls which ref runs `deploy/deplo ## 📝 License -[MIT](LICENSE) +Flightdeck is released under the [MIT License](LICENSE).