Files
honey-be/docs/GITEA_VPS_DEPLOY.md
Tihon 15498c8337
All checks were successful
Deploy to VPS / deploy (push) Successful in 52s
Initial setup, cleanup, VPS setup
2026-03-07 23:11:31 +02:00

15 KiB
Raw Blame History

Gitea Actions: Deploy honey-be to VPS on push to main

This guide sets up automatic deployment of honey-be to your Honey VPS (188.116.23.7) when you push to the main branch. The workflow runs on your Gitea runner, syncs the repo via rsync over SSH, then runs the rolling-update script on the VPS.

Prerequisites

  • Gitea with Actions enabled and at least one runner registered (e.g. ubuntu-latest).
  • Honey VPS (188.116.23.7) with backend at /opt/app/backend/honey-be and scripts/rolling-update.staged.sh.
  • The Gitea server (or the machine where the runner runs) must be able to reach 188.116.23.7 over the network (e.g. outbound SSH). Gitea itself can stay Tailscale-only.

1. Create the deploy SSH key on your Mac

Where: Local Mac (Terminal).

1.1 Generate a dedicated deploy key (Ed25519, no passphrase):

ssh-keygen -t ed25519 -C "gitea-deploy-honey-be" -f ~/.ssh/gitea_deploy_honey_be -N ""

1.2 Where the keys are on your Mac:

File on your Mac Purpose
~/.ssh/gitea_deploy_honey_be Private key — you will paste this into Gitea (Step 3). Never put this on the Staged VPS.
~/.ssh/gitea_deploy_honey_be.pub Public key — you will put this on the Staged VPS (Step 2).

1.3 Optional: display the keys so you can copy them later.

To show the public key (for Step 2):

cat ~/.ssh/gitea_deploy_honey_be.pub

To show the private key (for Step 3 — paste into Gitea):

cat ~/.ssh/gitea_deploy_honey_be

Copy each output as a whole (including ssh-ed25519 ... for the public key and -----BEGIN ... KEY----- / -----END ... KEY----- for the private key). You can run these commands again anytime.


2. Put the public key on the Staged VPS

The Staged VPS is your Honey server: 188.116.23.7. The Gitea runner will SSH into this machine as root (or your deploy user), so the public key must be in that users authorized_keys on the Staged VPS.

2.1 — On your Local Mac: Copy the public key to the clipboard (so you can paste it on the VPS):

cat ~/.ssh/gitea_deploy_honey_be.pub | pbcopy

Or just note the single line that looks like:
ssh-ed25519 AAAAC3... gitea-deploy-honey-be

2.2 — Log in to the Staged VPS from your Mac:

ssh root@188.116.23.7

(Use the same user you normally use to manage this server, e.g. root or a user with sudo. If you use a different user, replace root in the next steps with that user.)

2.3 — On the Staged VPS (188.116.23.7): Ensure .ssh exists and add the public key.

Run these commands one by one on the Staged VPS (after youre logged in via SSH):

mkdir -p ~/.ssh
chmod 700 ~/.ssh

Then add the public key. Either paste the line you copied (replace PASTE_YOUR_PUBLIC_KEY_LINE_HERE with the actual line):

echo 'PASTE_YOUR_PUBLIC_KEY_LINE_HERE' >> ~/.ssh/authorized_keys

Or, if you have the key in your Mac clipboard, on the Staged VPS you can do (from Mac, one line):

ssh root@188.116.23.7 "mkdir -p ~/.ssh && chmod 700 ~/.ssh && echo '$(cat ~/.ssh/gitea_deploy_honey_be.pub)' >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

If you ran the echo ... >> authorized_keys manually on the VPS, set permissions:

chmod 600 ~/.ssh/authorized_keys

2.4 — Verify from your Mac: Check that the deploy key can log in without a password:

ssh -i ~/.ssh/gitea_deploy_honey_be root@188.116.23.7 "echo OK"

You should see OK. If you get "Permission denied (publickey)", the public key was not added correctly to ~/.ssh/authorized_keys on the Staged VPS.


3. Put the private key into Gitea (repository secret)

Where: Private key stays on your Mac; you only paste its contents into Gitea in the browser.

3.1 — On your Local Mac: Show the private key so you can copy it:

cat ~/.ssh/gitea_deploy_honey_be

Copy the entire output, including:

  • -----BEGIN OPENSSH PRIVATE KEY-----
  • all lines in the middle
  • -----END OPENSSH PRIVATE KEY-----

3.2 — In Gitea (browser): Add it as a repository secret.

  1. Open your repo: http://100.122.146.65:3000/admin/honey-be (or your Gitea URL over Tailscale).
  2. Go to SettingsSecrets and VariablesActions.
  3. Under Repository Secrets, click Add Secret.
  4. Name: DEPLOY_SSH_PRIVATE_KEY
  5. Value: Paste the full private key you copied from the previous command. Paste once, with no extra spaces or blank lines before/after; the key must start with -----BEGIN OPENSSH PRIVATE KEY----- and end with -----END OPENSSH PRIVATE KEY-----. Do not paste the .pub (public) file by mistake — that will cause "Error loading key ... invalid format" in the workflow.
  6. Save.

Optional secrets (workflow has defaults):

Name Value When to set
DEPLOY_VPS_HOST 188.116.23.7 Only if your Staged VPS has a different IP.
DEPLOY_VPS_USER root Only if the deploy user is not root.
GITEA_HOST_IP e.g. 172.20.0.1 If checkout fails with "Could not resolve host: server", set this to the default gateway seen from the job container. Run a debug job that runs ip route show default | awk '{print $3}' and use that value. The workflow defaults to 172.20.0.1 if unset.

4. Add the workflow file to the repo and push it

The workflow is a YAML file that tells Gitea what to do when you push to main. It does not get “installed” anywhere except inside the repository.

4.1 — What the file is and where it lives

  • Path in repo: .gitea/workflows/deploy-vps.yaml
  • What it does: On every push to main, Gitea runs a job that: checks out the code → installs SSH/rsync → syncs the repo to the Staged VPS at /opt/app/backend/honey-be → runs sudo ./scripts/rolling-update.staged.sh on the VPS.
  • Gitea only runs workflows that exist on the branch you push. So this file must be committed and pushed to main.

4.2 — What you need to do

Where: Local Mac (in your honey-be project directory).

  1. Confirm the workflow file exists:

    cd /path/to/your/honey-be
    ls -la .gitea/workflows/deploy-vps.yaml
    
  2. If its there, add it to git, commit, and push to main:

    git add .gitea/workflows/deploy-vps.yaml
    git commit -m "Add VPS deploy workflow"
    git push origin main
    
  3. If the file is not there, create the directory and the file (the file contents are in this repo), then run the same git add / git commit / git push as above.

After the push, Gitea will see the workflow. It will run only when a runner is available (Step 5). So you can push the workflow first and set up the runner next, or the other way around.


5. Set up Gitea Actions and the runner

Gitea needs Actions enabled and at least one runner registered. The runner is the machine (or container) that actually runs the workflow steps. Your Gitea runs on a VPS with Docker; the runner is usually the act_runner container next to Gitea.

5.1 — Enable Actions (if not already)

Where: Gitea in the browser (admin or repo).

  • Site-wide: Log in as admin → Site AdministrationActions → enable Enable Actions.
  • Or at repo level: open honey-beSettingsActions → enable if there is an option.

5.2 — Ensure the runner container is running

Where: Gitea VPS (the server where Giteas Docker runs, e.g. 100.122.146.65 over Tailscale).

SSH into the Gitea server and check that both gitea and gitea_runner (or your runner container name) are up:

docker ps

You should see something like gitea and gitea_runner. If the runner container is stopped:

cd ~/gitea   # or wherever your docker-compose.yml is
docker compose up -d

5.3 — Get the runner registration token from Gitea

Where: Gitea in the browser.

  1. Open the honey-be repository.
  2. Go to SettingsActionsRunners.
  3. Click Create new runner (or Add runner / Register runner).
  4. Gitea will show a registration token and often a command or instructions. Copy the token (youll use it in the next step if the runner is not already registered).

5.4 — Register the runner (if it isnt already)

Where: Gitea VPS (SSH).

Your docker-compose must set GITEA_INSTANCE_URL to a URL the runner container can reach. Use the Docker service name, not 127.0.0.1:

  • Use: GITEA_INSTANCE_URL=http://server:3000 (so the runner resolves server on the Docker network).
  • Do not use: GITEA_INSTANCE_URL=http://127.0.0.1:3000 — from inside the runner container, that is the container itself, so the runner stays "Offline" and never connects.

Your docker-compose may already set GITEA_RUNNER_REGISTRATION_TOKEN and the runner registers on startup. Check in Gitea: SettingsActionsRunners. If you see a runner with status Idle and label ubuntu-latest, you can skip to 5.5.

If no runner appears (or it stays "Offline"), register or re-register on the Gitea VPS. If you changed GITEA_INSTANCE_URL, clear the runners persisted state first so it uses the new URL:

cd ~/gitea
docker compose stop runner
rm -rf ./data/runner/*
docker compose up -d --force-recreate runner

If you still need to register manually:

docker exec -it gitea_runner sh

Inside the container:

act_runner register --instance http://server:3000 --token PASTE_TOKEN_FROM_STEP_5.3

Then exit and restart the runner container so it runs the daemon:

exit
docker restart gitea_runner

5.5 — Check that the runner has the right label

Where: Gitea in the browser.

  1. Go to honey-beSettingsActionsRunners.
  2. You should see at least one runner with:
    • Status: Idle (or Running when a job is active)
    • Labels: must include ubuntu-latest, because the workflow file has runs-on: ubuntu-latest.

If your runner has a different label (e.g. linux), you have two options:

  • Option A: In Gitea when registering the runner, add the label ubuntu-latest (if the UI lets you choose labels).
  • Option B: Edit .gitea/workflows/deploy-vps.yaml and change the line runs-on: ubuntu-latest to your runners label (e.g. runs-on: linux), then commit and push.

5.6 — Summary

  • Actions enabled in Gitea.
  • Runner container running on the Gitea VPS.
  • Runner registered and visible under SettingsActionsRunners with label ubuntu-latest (or workflow updated to match your label).

6. Test the deployment

Do this after the workflow file is on main (Step 4) and the runner is set up (Step 5).

6.1 — Trigger a run

Push a commit to main (e.g. a small change or the workflow/docs you added):

cd /path/to/your/honey-be
git add .gitea/workflows/deploy-vps.yaml docs/GITEA_VPS_DEPLOY.md
git commit -m "Add VPS deploy workflow and guide"
git push origin main

6.2 — Check the run in Gitea

Where: Gitea in the browser.

  1. Open honey-beActions (tab in the repo).
  2. You should see a run for the “Deploy to VPS” workflow. Open it.
  3. Confirm all steps are green. If something fails, open the failed step to see the log.

6.3 — Check the Staged VPS

Where: Staged VPS (188.116.23.7) or your Mac (SSH to VPS).

  1. SSH in: ssh root@188.116.23.7
  2. Check that code was updated: ls -la /opt/app/backend/honey-be
  3. Check that the app restarted: docker ps (or your usual way to verify the backend is running).

Troubleshooting

Runner stays "Offline" / "Last Online Time: Never" / "Cannot ping the Gitea instance server"

  • Cause: The runner container is trying to reach Gitea at http://127.0.0.1:3000. From inside the runner container, 127.0.0.1 is the container itself, not the Gitea server, so the connection is refused.
  • Fix:
    1. In your docker-compose on the Gitea VPS, set GITEA_INSTANCE_URL=http://server:3000 (use the Docker service name of the Gitea container, e.g. server).
    2. Clear the runner's persisted state and recreate the container so it re-registers with the new URL:
      cd ~/gitea
      docker compose stop runner
      rm -rf ./data/runner/*
      docker compose up -d --force-recreate runner
      
    3. In Gitea → SettingsActionsRunners, the runner should show Idle within a few seconds. If you see a new runner and the old one still "Offline", you can remove the old one in the UI.

Checkout fails: "Could not resolve host: server" / "fatal: unable to access 'http://server:3000/...'"

  • Cause: The workflow job runs inside a separate Docker container (started by the runner). That job container is not on the same Docker network as Gitea, so the hostname server does not resolve there. Changing Gitea's LOCAL_ROOT_URL or the host's /etc/hosts does not help, because the job container has its own network.
  • Fix: The deploy workflow in this repo already uses a manual checkout that clones via the runner host's IP instead of server. If checkout still fails:
    1. Add repository secret GITEA_HOST_IP with the default gateway as seen from the job container. To get it: run a one-off debug workflow that runs ip route show default | awk '{print $3}' and use the printed value (often 172.20.0.1 or 172.17.0.1).
    2. If you don't set the secret, the workflow defaults to 172.20.0.1; if your Docker uses a different gateway, set GITEA_HOST_IP to that value.

Setup SSH fails: "Error loading key ... invalid format"

  • Cause: The DEPLOY_SSH_PRIVATE_KEY secret in Gitea is not valid: pasted with wrong line breaks, truncated, or the public key (.pub) was pasted by mistake.
  • Fix:
    1. On your Mac, verify the private key file: ssh-keygen -y -f ~/.ssh/gitea_deploy_honey_be. If that fails, generate a new key (Step 1) and add the new public key to the VPS and the new private key to Gitea.
    2. Copy the full private key again: cat ~/.ssh/gitea_deploy_honey_be | pbcopy (or open the file and copy everything).
    3. In Gitea → SettingsSecrets and VariablesActions, edit DEPLOY_SSH_PRIVATE_KEY and paste the entire key. It must start with -----BEGIN OPENSSH PRIVATE KEY----- and end with -----END OPENSSH PRIVATE KEY-----, with no extra blank lines or spaces at the start/end. Make sure you are pasting the private key file, not the .pub file.
    4. Save and re-run the workflow.

Other issues

  • Permission denied (publickey) (during rsync or SSH to Staged VPS)
    Check: public key in authorized_keys on the Staged VPS, private key in DEPLOY_SSH_PRIVATE_KEY, no extra spaces/newlines when pasting. From your Mac, test: ssh -i ~/.ssh/gitea_deploy_honey_be root@188.116.23.7 "echo OK".

  • Runner doesnt pick up the job
    In Gitea: SettingsActionsRunners. Confirm runner is “idle” and has label ubuntu-latest.

  • rsync or SSH fails from the job
    The job runs on the Gitea VPS (in a container). Ensure the Gitea VPS can reach the Staged VPS (188.116.23.7) on port 22. From the Gitea VPS host, test: ssh -i /path/to/private_key root@188.116.23.7 "echo OK".

  • sudo or script fails on VPS
    SSH in as the deploy user and run manually:
    cd /opt/app/backend/honey-be && sudo ./scripts/rolling-update.staged.sh
    Fix permissions or sudo rules as needed.