How to Deploy a Binary Application with Dewy: Complete Guide for Go and Compiled Binaries
Deploy a binary application with Dewy by packaging your compiled executable as a <name>_<os>_<arch>.tar.gz archive, publishing it to a supported registry such as GitHub Releases, and running the dewy server command with your registry URL and binary path specified after the -- separator.
Dewy is an open-source deployment agent written in Go that automates the release management of binary applications. Whether you are deploying a Go microservice, a Rust CLI tool, or any compiled executable, Dewy handles polling for updates, atomic deployments, and graceful process restarts. This guide explains how to deploy a binary application with Dewy using the server command and the underlying implementation in the linyows/dewy repository.
How Dewy Deploys Binary Applications
When you run the server command, Dewy treats your binary as a server-type application and executes a continuous deployment loop. The Run method in main/dewy.go orchestrates this process by performing the following steps:
- Polls the registry (GitHub Releases, S3, GCS, OCI, etc.) for the latest version using the
Current()method defined inregistry/registry.go. - Downloads the artifact (your binary archive) and caches it in the local key-value store (
kvs/file.go). - Extracts the archive into a timestamped release directory under
./releases/. - Atomically updates the
currentsymlink to point to the new release usingos.Renamein thedeploymethod. - Starts or restarts the binary via the supplied command line, using
github.com/linyows/server-starterto manage the process lifecycle.
By default, Dewy retains the 7 most recent releases (keepReleases = 7 in dewy.go), automatically cleaning up older versions to conserve disk space.
Packaging Your Binary for Dewy
Dewy expects binary applications to follow a specific packaging convention. The artifact name must contain the target operating system and architecture, or you must explicitly specify the artifact name using registry options.
Naming Convention
Package your binary using the format:
<app>_<os>_<arch>.tar.gz
For example, a Go binary built for Linux AMD64 should be named myapp_linux_amd64.tar.gz. Dewy automatically detects the current OS and architecture when polling the registry, selecting the appropriate artifact from the release.
Archive Structure
The archive should contain the executable at the root level or within a predictable path. When Dewy extracts the archive to ./releases/<timestamp>/, it creates a current symlink pointing to this directory. Your deployment command should reference the binary via this symlink path, such as /opt/myapp/current/myapp.
Step-by-Step Deployment Guide
Follow these steps to deploy a binary application with Dewy from compilation to production execution.
1. Build and Package the Binary
Compile your Go application for the target platform and create a compressed archive:
# Build the binary
GOOS=linux GOARCH=amd64 go build -o myapp
# Package as tar.gz (Dewy expects this format)
tar -czf myapp_linux_amd64.tar.gz myapp
2. Publish to a Supported Registry
Upload the artifact to a registry that Dewy can poll. GitHub Releases is the most common choice:
# Create a release and upload the artifact
gh release create v1.0.0 myapp_linux_amd64.tar.gz \
--title "v1.0.0" \
--notes "Initial release"
Dewy supports multiple registry backends implemented in the registry/ directory, including AWS S3 (s3.go), Google Cloud Storage (gcs.go), and OCI registries.
3. Run the Dewy Server Command
Execute the server command to start the deployment agent. The command-line parsing logic in main/cli.go handles the --registry flag and the -- separator that distinguishes Dewy options from your binary's command line.
dewy server \
--registry ghr://myorg/myapp \
--notifier slack://#deploys?title=myapp \
-p 8080 \
-l info \
-- /opt/myapp/current/myapp
Key parameters explained:
--registry ghr://myorg/myapp: Specifies the GitHub Releases registry endpoint.-p 8080: Defines the port for the server (optional, required only if your binary is an HTTP server that Dewy should proxy or monitor).--: Separator indicating the end of Dewy options and the start of the command to execute./opt/myapp/current/myapp: Path to the binary via thecurrentsymlink that Dewy manages.
4. Configure Deployment Hooks (Optional)
Add --before-deploy-hook and --after-deploy-hook to execute custom scripts during the deployment lifecycle. The execHook function in dewy.go runs these via /bin/sh -c and reports results to your notifier.
dewy server \
--registry ghr://myorg/myapp \
--before-deploy-hook "cp /opt/myapp/current/myapp /backup/myapp_$(date +%F_%T)" \
--after-deploy-hook "/opt/myapp/current/myapp --migrate" \
-- /opt/myapp/current/myapp
Key Implementation Details
Understanding how Dewy manages binary deployments at the code level helps troubleshoot issues and optimize your configuration.
Registry Polling and Version Detection
Dewy abstracts registry interactions through the Registry interface defined in registry/registry.go. Each implementation (GitHub Releases in ghr.go, S3 in s3.go) provides a Current() method that returns a CurrentResponse containing the latest tag and artifact URL.
The polling interval and registry-specific options (such as artifact= to override the default naming pattern) are parsed in main/cli.go and passed to the registry driver.
Atomic Release Switching
To ensure zero-downtime deployments, Dewy performs atomic updates using symlinks. The deploy method in main/dewy.go (lines 32-55) extracts the new release into a timestamped directory under ./releases/, creates a temporary symlink pointing to this directory, and then uses os.Rename to atomically replace the current symlink.
This approach ensures that the current path always points to a complete, valid release, preventing partial deployments from serving traffic.
Process Management with Server Starter
Dewy leverages github.com/linyows/server-starter to manage the lifecycle of your binary application. The startServer and restartServer functions in main/dewy.go handle process spawning and graceful restarts.
When a new version is detected and deployed, Dewy sends a SIGHUP signal to the running process (or starts it if not running), allowing the application to reload without dropping connections. The Admin API runs on localhost:17539 by default, providing endpoints at /api/status and /api/containers for monitoring deployment state.
Summary
Deploying binary applications with Dewy provides a robust, zero-downtime continuous deployment pipeline for compiled executables. Key takeaways include:
- Package binaries using the
<name>_<os>_<arch>.tar.gznaming convention for automatic artifact detection. - Use the
servercommand to enable continuous polling, atomic deployments via symlinks, and automatic process restarts. - Reference the binary via the
currentsymlink path (e.g.,/opt/myapp/current/myapp) in your command arguments after the--separator. - Configure hooks using
--before-deploy-hookand--after-deploy-hookto run custom logic during the deployment lifecycle. - Monitor deployments through the Admin API on
localhost:17539or configured notifiers like Slack.
Frequently Asked Questions
How does Dewy handle zero-downtime deployments for binary applications?
Dewy achieves zero-downtime deployments through atomic symlink switching and graceful process restarts. When a new version is detected, Dewy extracts the artifact into a timestamped directory and creates a temporary symlink pointing to it. The deploy method in main/dewy.go then uses os.Rename to atomically replace the current symlink, ensuring the path always points to a complete release. The running binary is then gracefully restarted via SIGHUP using the server-starter library, allowing the application to reload without dropping active connections.
What registry formats does Dewy support for binary artifacts?
Dewy supports multiple registry backends through its pluggable Registry interface defined in registry/registry.go. The built-in implementations include GitHub Releases (ghr.go), AWS S3 (s3.go), Google Cloud Storage (gcs.go), and OCI registries. Each registry driver implements the Current() method, which returns the latest version tag and artifact URL. For GitHub Releases, use the format ghr://owner/repo, while S3 and GCS use their respective URL schemes with optional artifact= query parameters to override default naming patterns.
How do I configure pre-deployment and post-deployment hooks?
You can configure custom scripts to run during the deployment lifecycle using the --before-deploy-hook and --after-deploy-hook flags when executing the dewy server command. These hooks are executed via /bin/sh -c by the execHook function in main/dewy.go, and their output is logged and sent to your configured notifier. For example, you can specify --before-deploy-hook "cp /opt/app/current/binary /backup/binary_$(date +%F)" to create backups before deployment, or --after-deploy-hook "/opt/app/current/binary --migrate" to run database migrations after the new version is activated.
What is the purpose of the -- separator in the Dewy server command?
The -- separator in the dewy server command distinguishes between Dewy's own command-line options and the command to execute your binary application. Everything before -- is parsed by the CLI handler in main/cli.go and configures Dewy's behavior (registry URL, notifiers, ports, hooks). Everything after -- is treated as the literal command line to start your binary, typically referencing the current symlink path such as /opt/myapp/current/myapp. This separation ensures that flags intended for your application (like -port or -config) are not intercepted by Dewy's flag parser.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →