| name | prod-deploy |
| description | Deploy services to feedsubscription.com production. Use when the user asks to deploy, push to prod, restart a container on prod, or rebuild an image on production. Handles git push, SSH ControlMaster setup, and running make targets remotely. |
Prod Deploy
Deploys one or more services to feedsubscription.com.
Standard workflow
1. Push commits
git push
2. Establish SSH ControlMaster
ssh -M -S ~/.ssh/control-feedsubscription -o ControlPersist=10m -fN feedsubscription.com
echo "ControlMaster established"
Skip if already established (the command will silently succeed or fail harmlessly).
3. Deploy
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'cd ~/src/rss-email-subscription && git pull && make <targets> start'
Replace <targets> with the services to rebuild before restarting.
Service → make target mapping
| Service | Target | Notes |
|---|
| app | app | Also rebuilds delmon (FROM app) |
| certbot | certbot | |
| logger | logger | |
| website | website | |
| smtp-in | smtp-in | |
| smtp-out | smtp-out | |
| resolver | resolver | |
| delmon | delmon | Or just rebuild app |
make start (always included) runs docker compose up --remove-orphans --detach
and restarts only the containers whose images changed.
Examples
Deploy only app:
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'cd ~/src/rss-email-subscription && git pull && make app start'
Deploy certbot, logger, and website together:
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'cd ~/src/rss-email-subscription && git pull && make certbot logger website start'
Deploy all images (full rebuild):
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'cd ~/src/rss-email-subscription && git pull && make all-images start'
Smoke test (optional)
If the user asks for a smoke test after deploying app, trigger a feed check by removing lastPostMetadata.json and sending HUP:
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'rm src/rss-email-subscription/.tmp/docker-data/accounts/*/feeds/gurdiga/lastPostMetadata.json && docker kill -s HUP app'
Then confirm the sending report appeared in app.log (wait ~15s first):
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'grep "Sending report" src/rss-email-subscription/.tmp/logs/feedsubscription/app.log | grep "gurdiga" | tail -3'
Look for "sent":N,"failed":0 in the report data.
Then confirm delivery via smtp-out log:
ssh -S ~/.ssh/control-feedsubscription feedsubscription.com \
'docker logs smtp-out 2>&1 | tail -40'
Look for status=sent (250 2.0.0 OK) for each queued message, and removed confirming the queue cleared. Any status=deferred or status=bounced lines indicate a delivery problem.
Notes
- Always
git push before deploying so git pull on prod gets the latest commits.
make start is always appended — it's a no-op for containers whose image didn't change.
- Timeout: allow up to 5 minutes for builds that compile TypeScript (app) or download pip packages (certbot).
- After certbot rebuilds: verify with
docker exec certbot python -c "import certbot; import OpenSSL; print('ok')".