This repo now includes an EC2 deployment workflow at .github/workflows/deploy-ec2.yml.
What it does:
- triggers automatically on pushes to
master - can also be run manually from the GitHub Actions tab
- connects to your EC2 instance over SSH
- syncs the repo to the server
- uploads the runtime
.env - builds the Docker image on EC2
- runs
python -m bot.profile_runner <paper|live> validate spyon EC2 (orbtcifDEPLOY_MARKET=btc) - installs a cron job that runs the chosen profile once an hour in
America/New_York
Create these repository or environment secrets:
EC2_HOST: public DNS name or public IP of the instanceEC2_USER: SSH user, usuallyubuntuEC2_SSH_KEY: private key used by GitHub Actions to SSH into EC2EC2_ENV_FILE: full contents of the server-side.env
Example EC2_ENV_FILE source:
- start from
.env.example - fill in your Alpaca keys
- keep
ALPACA_PAPER_*andALPACA_LIVE_*values there - keep only real secrets in this GitHub secret, not in the repo
Optional repository variables:
EC2_APP_DIR: defaults to/home/ubuntu/trading-botEC2_PORT: defaults to22
Use Ubuntu 22.04 or 24.04 on EC2.
- SSH into the instance.
- Install Docker, the Compose plugin, and cron:
sudo apt-get update
sudo apt-get install -y docker.io docker-compose-plugin cron
sudo systemctl enable --now docker
sudo systemctl enable --now cron
sudo usermod -aG docker "$USER"
newgrp docker- Create the app directory:
mkdir -p /home/ubuntu/trading-bot- Make sure the SSH user from
EC2_USERcan log in non-interactively from GitHub Actions.
Recommended path:
- generate a dedicated SSH key pair for deployment
- add the public key to
~/.ssh/authorized_keyson EC2 - store the private key in the
EC2_SSH_KEYGitHub secret
- Confirm the instance user can run Docker without
sudo:
docker version
docker compose version- Push this repo to GitHub with the new workflow files.
- Add the secrets listed above.
- Open
Actionsin GitHub. - Run
Deploy To EC2. - Choose
liveorpaper. - Leave
install_cronenabled unless you want a code-only deploy.
On every later push to master, the workflow will auto-deploy the live profile.
Check the installed cron entries:
crontab -lCheck the last deploy logs from GitHub Actions in the Actions tab.
Check runtime output on the server:
ls -la /home/ubuntu/trading-bot/logs
tail -n 50 /home/ubuntu/trading-bot/logs/live_cron.log
tail -n 50 /home/ubuntu/trading-bot/logs/paper_cron.logIf you want to run one profile manually on the server after a deploy:
cd /home/ubuntu/trading-bot
docker compose run --rm trade
docker compose run --rm paperIf you want a different schedule, set CRON_SCHEDULE before running deploy/ec2/install_cron.sh, or edit the script default.
Current default schedule:
- once an hour, 5 minutes past the hour (
5 * * * *) - every day
America/New_Yorktimezone
The default deploy market is spy (SYMBOL=TSLA, see config/live_spy.env),
which trades hourly bars during the equity session — the bot itself checks
market hours and holds outside them, so running the cron job around the
clock is harmless, just a no-op most of the day. The btc market
(config/live_btc.env) also trades hourly bars now, so the same schedule
applies; set DEPLOY_MARKET=btc on the workflow dispatch to deploy it
instead. If you change a profile's TIMEFRAME_MINUTES, update
CRON_SCHEDULE to match — running the bot much more often than its bar
interval just wastes API calls and log lines, since cooldown and
pending-order checks will no-op the extra invocations.