FTL is a deployment tool that reduces complexity for projects that don't require extensive orchestration infrastructure. It provides automated deployment to cloud providers like Hetzner, DigitalOcean, Linode, and custom servers without the overhead of CI/CD pipelines or container orchestration platforms.
- Single YAML configuration file with environment variable substitution
- Zero-downtime deployments
- Automatic SSL/TLS certificate management
- Docker-based deployment with built-in health checks
- Integrated Nginx reverse proxy
- Multi-provider support (Hetzner, DigitalOcean, Linode, custom servers)
- Fetch and stream logs from deployed services
- Establish SSH tunnels to remote dependencies
-
Via Homebrew (macOS and Linux)
brew tap yarlson/ftl brew install ftl
-
Download from GitHub releases
curl -L https://github.com/yarlson/ftl/releases/latest/download/ftl_$(uname -s)_$(uname -m).tar.gz | tar xz sudo mv ftl /usr/local/bin/
-
Build from source
go install github.com/yarlson/ftl@latest
Create an ftl.yaml
configuration file in your project directory:
project:
name: my-project
domain: my-project.example.com
email: [email protected]
servers:
- host: my-project.example.com
port: 22
user: my-project
ssh_key: ~/.ssh/id_rsa
services:
- name: my-app
image: my-app:latest
port: 80
health_check:
path: /
interval: 10s
timeout: 5s
retries: 3
routes:
- path: /
strip_prefix: false
dependencies:
- name: postgres
image: postgres:16
volumes:
- postgres_data:/var/lib/postgresql/data
env:
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
- POSTGRES_USER=${POSTGRES_USER:-postgres}
- POSTGRES_DB=${POSTGRES_DB:-app}
volumes:
- postgres_data
Environment variables in the configuration can be:
- Required:
${VAR_NAME}
- Must be set in the environment - Optional with default:
${VAR_NAME:-default_value}
- Uses default if not set
Set up your server with the required dependencies:
ftl setup
This command will:
- Install Docker and other necessary packages on your server
- Configure firewall rules
- Set up user permissions
- Initialize Docker networks
Build Docker images for application services:
ftl build [flags]
--skip-push
: Skip pushing images to the registry after building.
- Build and push all services:
ftl build
- Build all services but skip pushing to the registry:
ftl build --skip-push
Deploy your application to the configured servers:
ftl deploy
This command will:
- Connect to your servers via SSH
- Pull Docker images specified in your configuration
- Start new containers with health checks
- Configure the Nginx reverse proxy
- Manage SSL/TLS certificates via ACME
- Perform zero-downtime container replacement
- Clean up unused resources
Retrieve logs from your deployed services:
ftl logs [service] [flags]
-f
,--follow
: Stream logs in real-time.-n
,--tail <lines>
: Number of lines to show from the end of the logs (default is 100 if-f
is used).
- Fetch logs from all services:
ftl logs
- Stream logs from a specific service:
ftl logs my-app -f
- Fetch the last 50 lines of logs from all services:
ftl logs -n 50
- Fetch logs from a specific service with a custom tail size:
ftl logs my-app -n 150
Establish SSH tunnels for your dependencies, allowing local access to services running on your server:
ftl tunnels [flags]
-s
,--server <server>
: (Optional) Specify the server name or index to connect to, if multiple servers are defined.
- Establish tunnels to all dependency ports:
ftl tunnels
- Specify a server to connect to (if multiple servers are configured):
ftl tunnels --server my-project.example.com
The ftl tunnels
command is useful for:
- Accessing dependency services (e.g., databases) running on your server from your local machine
- Simplifying local development by connecting to remote services without modifying your code
- Testing and debugging your application against live dependencies
All commands include detailed error reporting and user feedback through spinners and console messages. Examples:
- Commands gracefully handle configuration file parsing issues.
- Detailed error messages are provided for server connection or dependency issues.
Commands like build
and tunnels
leverage concurrent operations to improve performance. For example:
ftl build
builds and optionally pushes images for all services concurrently.ftl tunnels
establishes SSH tunnels for multiple dependencies simultaneously.
To ensure optimal usage:
- Ensure all dependencies have
ports
specified inftl.yaml
forftl tunnels
to function. - Use health checks in service definitions to ensure reliability during deployment and build processes.
The ftl-examples repository contains reference implementations:
- Flask - Python Flask application with PostgreSQL
- More examples coming soon
Each example provides a complete project structure with configuration files and deployment instructions.
# Clone repository
git clone https://github.com/yarlson/ftl.git
# Install dependencies
cd ftl
go mod download
# Run tests
go test ./...
Contributions are welcome. Please ensure:
- Code follows project style guidelines
- Tests pass and new tests are added for new features
- Documentation is updated accordingly