Step 1
Register and add your key
Create an account, then paste in your SSH public key — usually the contents of ~/.ssh/id_ed25519.pub. If you do not have one yet, run ssh-keygen -t ed25519.
Docs
There is no CLI to install and no configuration file to write. If you can copy a folder, you can deploy.
Step 1
Create an account, then paste in your SSH public key — usually the contents of ~/.ssh/id_ed25519.pub. If you do not have one yet, run ssh-keygen -t ed25519.
Step 2
Choose a name, such as my-site. It is live at my-site.myotter.dev straight away, with a certificate already issued.
Step 3
Point the command at whatever folder your build produced — dist, build, public, _site. The site switches over once the whole upload has arrived.
scp -r ./dist/. my-site@push.cleverotter.eu:/
The trailing /. means “the contents of dist”, not “dist itself”. We reject the ambiguous form rather than guess and publish a site one folder deep.
Other ways in
It is a standard SSH endpoint, so the tools on your machine and in your CI already speak to it.
rsync — only sends what changed
rsync -az --delete ./dist/ my-site@push.cleverotter.eu:/
tar — fastest for very many small files
tar czf - -C ./dist . | ssh my-site@push.cleverotter.eu upload
sftp — if that is what your tooling speaks
sftp my-site@push.cleverotter.eu
GitHub Actions
Generate a key pair, add the public half to your site as a deploy key, and store the private half as a repository secret. A key needs no prompt, so CI never has to answer one.
- name: Deploy to CleverOtter
run: |
mkdir -p ~/.ssh && chmod 700 ~/.ssh
printf '%s\n' "$DEPLOY_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%s\n' "$HOST_KEY" > ~/.ssh/known_hosts
scp -r ./dist/. my-site@push.cleverotter.eu:/
env:
DEPLOY_KEY: ${{ secrets.CLEVEROTTER_DEPLOY_KEY }}
HOST_KEY: ${{ secrets.CLEVEROTTER_HOST_KEY }}
Both values are shown in the dashboard under Site → Deploy keys. Pinning our host key rather than accepting it on first use is what stops a hijacked DNS answer collecting your credential.
Deployments exit non-zero when they fail, so a broken build fails the job instead of quietly doing nothing.
Reference
Including the ones usually left to a support ticket.
If something goes wrong
Use ./dist/. rather than ./dist. Without it, scp copies the folder itself and your site would end up served one level down. We refuse it instead of publishing something you did not mean.
Nothing happened to your live site. Files are staged and validated before anything is published, so an interrupted upload is discarded. Run the command again.
Use a deploy key if you can — it needs no prompt. If you must use a token, note that piping it into scp does not work: OpenSSH reads the prompt from the terminal, not standard input, and CI runners have no terminal. Answer it with an askpass helper instead:
printf '#!/bin/sh\nprintf %s\\n "$CO_TOKEN"\n' > /tmp/ask && chmod 700 /tmp/ask
SSH_ASKPASS=/tmp/ask SSH_ASKPASS_REQUIRE=force DISPLAY=none scp -r ./dist/. my-site@push.cleverotter.eu:/
Your key was not recognised, so it is offering the token prompt instead. Check the key is registered in the dashboard, or paste a deploy token at the prompt.
From the dashboard, choose an earlier release and restore it. It takes under a second because nothing is re-uploaded — the site is simply repointed at a release that is still there.
Add it to the site in the dashboard, then point a CNAME at your site’s address. The certificate is issued on the first request and renewed automatically. Free on every tier.
Get started
Register, add a site, run one command. Free forever, no card.