Easily run different versions and instances of your web / server application during development - given a (fairly strict) set of requirements.
Requirements:
- The applications should be a single binary! Like a Rust application serving it's own static assets with Memory serve
- Etes is build for GitHub. It fetches the currently open Pull Requests and Releases and lets users login using GitHub OAuth.
- Binaries should be uploaded, prefereable from a GitHub action.
- Start new environments on the fly, from a list of Pull Requests or the latest releases
- Each environment has a unique random name (by combining a few words from a provided word list as a sub-domain)
- Users can shutdown the services they started
- Admins (configured by a list of GitHub usernames) can shut down any service
- configure a cutsom page title and favicon
- Live interface updates
- Bind trigger/latest and build/merge commits
Configuration options can be provided using the environment, or a configuration file.
A configuration file names config.toml should be placed in the current working directory.
Environment variables overwrite any options from the configuration file and should have a name prefixed by ETES_.
title: Page title and headergithub_token: GitHub token, no priviliges neccecary, only used for read-only access to PR's and Releases using the GraphQL APIgithub_owner: GitHub owner or organisationgithub_repo: GitHub repository namegithub_client_id: GitHub Oauth client IDgithub_client_secret: GitHub Oauth client secretauthorize_url: OAuth callback URLservice_domain: Parent domain under which services are served (e.g.example.com); service URLs are built ashttps://{name}.{service_domain}session_key: Session key for cookiesapi_key: API key for binary uploadscommand_args: Arguments passed to the binary, use {port} to interpolate the port numbercommand_env: Environment variables passed to the binaryfavicon: Emoji favicon or letterwords: List of words to combine into a unique service nameadmins: Github user names / handles of admins
max_services: Maximum number of concurrent services (default: 1000)server_port: Port for the main HTTP server (default: 3000)proxy_port: Port for the proxy server (default: 3001)branches: List of branch names (besides the default branch) whose latest commit is shown in the top bar, next to the latest release and main build. Executables for these commits are never cleaned up (default:[])
An example configuration file can be found in this repository.
GitHub action example:
deploy:
environment:
name: test
url: https://${{ github.sha }}.example.com
permissions:
contents: read
deployments: write
runs-on: ubuntu-latest
steps:
- name: Download build artifact
uses: actions/download-artifact@v4
with:
name: executable.bin
- name: Upload binary to Etes
run: |
curl -s \
-H "Authorization: Bearer ${{ secrets.ETES_API_KEY }}" \
-T ./executable.bin \
https://example.com/etes/api/v1/executable/${{ github.sha }}/${{ github.sha }}
A reverse proxy that terminates TLS connections should be configured. The base domain should point to server_port (default 3000) and all sub-domains should point to proxy_port (default 3001).
Example using caddy:
example.com {
reverse_proxy localhost:3000
}
*.example.com {
reverse_proxy localhost:3001
}
Service file:
[Unit]
Description=Etes
After=network.target
Wants=network-online.target
[Service]
Restart=always
Type=simple
ExecStart=/app/etes
WorkingDirectory=/app
User=app
Group=app
[Install]
WantedBy=multi-user.target
