Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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 `<owner>/<repo>@latest` or `<owner>/<repo>@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

Expand Down
32 changes: 12 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -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`.
Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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).