Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

The most maintainable pattern is to build and test on a GitHub-hosted runner, publish an immutable release, connect to the Linux VPS over SSH, activate that release, and verify its health. A self-hosted runner installed on the VPS is an alternative when the deployment needs direct Docker, filesystem, or service-manager access, but it puts runner patching and job isolation on you.

Choose the deployment architecture first

GitHub Actions supports two practical ways to move a repository to a VPS. In the first, GitHub provisions a temporary hosted runner for each job. The runner checks out the code, runs tests and the build, transfers a release over SSH, and exits. In the second, a self-hosted runner application runs continuously on the VPS and executes the job there.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Decision axis Hosted runner plus SSH Self-hosted runner on the VPS
Network path The VPS accepts an SSH connection from GitHub runner egress. The runner makes outbound connections to GitHub and runs deployment commands locally.
Maintenance GitHub manages the runner image; you still patch the VPS and its application. You patch and harden the operating system, runner application, and supporting software.
Isolation The job runs on GitHub-hosted infrastructure separate from your VPS. The job runs inside the VPS environment. A deployment environment does not container-isolate a self-hosted job.
Local access Artifacts, images, and commands cross SSH. Docker, the filesystem, systemd, and local networks are directly available.
Typical failures SSH reachability, host-key changes, key rotation, or artifact transfer errors. Runner offline status, host capacity, queueing, stale software, or compromise of the runner host.

Use hosted runners plus SSH when you want an ephemeral build environment and a small trust boundary on the server. Use a self-hosted runner only when local access materially simplifies the deployment and you are prepared to operate it as production infrastructure.

What you need before the first deployment

  • A Linux VPS with a stable hostname or IP address and only the inbound ports your application requires.
  • A non-root account dedicated to deployments.
  • The application runtime or Docker, a service manager such as systemd, and a release directory on the VPS.
  • A GitHub repository with a protected production branch, tag, or manual production dispatch.
  • A deployment SSH key pair, with the private key stored in GitHub Actions secrets and the public key installed for the deploy account.
  • A health endpoint or command that can prove the new release is serving correctly.
  • A rollback target, such as the preceding release directory or container image tag.

Decide what your build produces before writing the workflow. It may be a versioned archive containing compiled files and runtime metadata, or a container image tagged with the commit SHA. Do not make an unqualified latest tag your only reference: it is difficult to audit and can make rollback ambiguous.

#1 Best Overall
Sale
Compressed Air Duster,130000RPM Super Power Cordless Air Duster,Rechargeable Brushless Blower,3 Gear Adjustable Blower with LED Light,Dust Remover for Computer/House/Outdoor/Car
  • Powerful Turbo Fan:CAGIWIRU Electric Air Duster have reached speed up to 130000RPM,Can efficient remove dust and debris.With LED light and Three Adjustable Speed to meet with different cleaning tasks.
  • With Attached USB C Fasting Charging cable.Charing 3 hours,Enjoy up to 240 minutes of use on the lowest setting, For third speed can use for 25mins.with four charging options to meet with your needs.
  • Wide Application:Upgraded attached 5 different nozzles,making it suitable for a variety of scenes, such as car,pet, pc, keyboards, and other electronic devices. It also serves for office and home clean duster.
  • Handy Design & Portable:Cordless air duster electric nozzle is Light weight and small size, design and comfortable to hold and space saving, convenient to carry around. You can put it in your room or inside the car without taking up space.
  • Warranty & Support: Our Electric air duster comes with 5 years warranty and 24/7 customer service. During this period, if you have any questions,pls kindly feel free to contact us.

Prepare the VPS for a deployment account

Create a least-privilege user

Log in as an administrator through your provider’s console or an existing administrative account, then create a user that owns only the files and services needed by the application. The exact commands vary by distribution; this example illustrates the sequence on a Linux system:

sudo useradd --create-home --shell /bin/bash deploy
sudo install --directory --owner=deploy --group=deploy /srv/myapp/releases
sudo install --directory --owner=deploy --group=deploy /srv/myapp/shared

Grant narrowly scoped service-control permissions if the deploy user must restart a systemd unit. Avoid giving it a root SSH key or unrestricted administrative privileges. If a privileged operation is unavoidable, allow only that command through a narrowly defined sudo rule and review it like application code.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install the runtime and define the service

Install the language runtime, reverse proxy, Docker Engine, or other dependencies required by the application. Define a stable service name, for example myapp.service, and keep configuration that changes independently of a release in /srv/myapp/shared. A release directory should be immutable after activation; the current version can be represented by a symlink such as /srv/myapp/current.

Before involving GitHub Actions, prove that the deploy user can start the service and that a local health request succeeds. This separates server configuration failures from workflow failures.

Rank #2
EVEO® Screen Cleaner Spray Kit (Streak-Free) TV Screen Cleaner for Smart TV, Lcd, LEd, Oled | Computer Screen Cleaner Spray and Wipe Microfiber Cloth - TV, Monitor, Laptop, iPad, Car - 6.7oz 1 Pack
  • Screen Cleaner is Your Screen’s New Bestfriend! - EVEO is proud to present a screen cleaner that’s perfectly suited for your TV. Meet your new screen cleaner, computer screen cleaner, laptop cleaner, iPad cleaner, Macbook,tv cleaner or any other electronic device. Our screen cleaner spray and wipe along with the included plush microfiber cloth, easily removes dust, fingerprints & other smudges on the screen’s surface. Clean effectively for a streak-free screen
  • Gentle on your Screens - Our screen cleaner spray and wipes is compatible to be used even for the most sensitive LCD, LED, CRT, and OLED screens in proper use. Be at ease knowing that this product is compatible with all the major brands: LG, SONY, Samsung, Sharp, iPad, iPhone, Android screens, Kindle, PC monitors - we’ve got you covered! Can be used as LCD screen cleaner, tv cleaner, smart tv screen cleaner, and more
  • Premium Super Soft Plush Microfiber Cloth - Included in this efficient screen cleaning kit. This screen cleaner spray and wipe has our signature plush microfiber cloth specially designed to comply with screens and monitors and leave them streak-free. Has been shown to effectively absorbs stubborn stains, zero streaks, and no fiber shedding. Always use this together with our screen cleaner for the best results
  • Easy-to-Use Screen Cleaner Kit + microfiber cleaning cloth - The EVEO Screen Cleaning Kit will easily be your new favorite tool when it comes to taking care of the things you love most, quick and easy solution for a streak-free screen. Simply screw on the sprayer gun on the screen cleaner bottle. Spray the cleaning liquid onto the microfiber cloth, then wipe the screen until desired cleanliness & shine is achieved.
  • Quality Screen Care Kit Worth Purchasing - Enjoy a convenient Screen Cleaner anytime, anywhere you need it. Your satisfaction is our top priority. We stand behind the quality of our products and that’s why, you shouldn’t be worrying at all. We manufacture the Best Screen Cleaner. and can be used for laptop cleaning kit, laptop screen cleaner, tv screen cleaner for smart tv. MacBook screen cleaner, monitor cleaner or screen cleaner spray for electronic devices with microfiber cleaning cloth

Restrict network exposure

Allow SSH only from the addresses and access path you actually use when practical, and expose the application through the intended HTTP or HTTPS entry point. Do not open database or administration ports to the public internet merely to make a deployment easier.

Create and store the deployment SSH key

  1. Generate a key pair on a trusted administrator workstation, specifically for this repository or environment. Do not reuse a personal login key.
  2. Append the public key to the deploy user’s ~/.ssh/authorized_keys on the VPS and set ownership and permissions so SSH will accept it.
  3. In the repository’s Settings → Secrets and variables → Actions, create secrets for the private key, VPS host, SSH port, and deploy username. Put production-only values in a GitHub deployment environment rather than repository-wide secrets.
  4. Store the VPS host key, or a reviewed known-hosts entry, as a secret as well. Installing an unverified key returned by an ad-hoc network lookup defeats host authentication.
  5. Keep registry credentials, application secrets, and database credentials in the same protected environment, never in workflow YAML or committed files.

Rotate the key when a repository, runner, or team member no longer needs access. Remove the corresponding public key from authorized_keys at the same time.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Build once and deploy over SSH from a hosted runner

A hosted-runner workflow should have one authoritative build. The artifact produced by that build is the object sent to the VPS; do not rebuild different source revisions on the server.

Trigger only an intentional production deployment

Use a protected branch, a version tag, or a manual dispatch tied to a production environment. The environment can require an approval before the job receives production secrets. Keep the workflow permission set small; for a deployment that only reads the repository, contents: read is usually sufficient.

Rank #3
BladeHawks RGB Gaming Mouse Pad Extra Large Extended 31.5x12 Inch-Black
  • 【Large size】:Measuring 800 x 300 mm/ 31. 5×12 inches, which is wider and taller than others. Large mouse pad can perfectly fit your keyboard and mouse of any size, and there is also ample space for peripherals such as phones, tablets, etc.
  • 【LED backlight mouse pad】:Blade Hawks RGB mouse pad provides 7 static modes and 7 dynamic modes will give you the options you are looking for. Power-off memory function remembers the last lighting mode you selected. The super glow fiber Chroma will give you a colorful gaming setup that you want.
  • 【Anti-slip rubber base】:Made from Natural rubber, this gaming mousepad will firmly grip your desktop, allowing you to enjoy the ultimate precision in the games you are most passionate about. It also comes with a texture that enhances this ability even further.
  • 【Smooth and waterproof surface】: Micro-textured cloth surface, for extremely precise mouse control and a smooth movement. When liquid splashes on the gaming mouse pad, it forms water droplets and slides down. Will not delay your work or gameplay.
  • 【Plug and play】: This mouse and keyboard pad is powered by USB, plug and play, no driver required. One button control light modes. Press one time to change the lighting mode, press twice to change the brightness, press and hold about 3 seconds turn ON/OFF.

Example workflow skeleton

The following workflow assumes the repository has scripts that run tests and create a dist directory. Replace those commands with the project’s actual build commands, but preserve the order: checkout, test, build, package, transfer, activate, and verify.

name: Deploy

on:
push:
branches: [main]
workflow_dispatch:

permissions:
contents: read

jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- name: Check out source
uses: actions/checkout@<reviewed-commit-sha>

- name: Install dependencies
run: ./scripts/install-dependencies.sh

- name: Run tests
run: ./scripts/test.sh

- name: Build
run: ./scripts/build.sh

- name: Package immutable release
run: tar -czf release-${GITHUB_SHA}.tgz dist

- name: Configure SSH
shell: bash
env:
SSH_PRIVATE_KEY: ${{ secrets.PRODUCTION_SSH_PRIVATE_KEY }}
SSH_KNOWN_HOSTS: ${{ secrets.PRODUCTION_SSH_KNOWN_HOSTS }}
run: |
install -d -m 700 ~/.ssh
printf '%sn' "$SSH_PRIVATE_KEY" > ~/.ssh/id_ed25519
chmod 600 ~/.ssh/id_ed25519
printf '%sn' "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts

- name: Copy release
env:
VPS_HOST: ${{ secrets.PRODUCTION_VPS_HOST }}
VPS_PORT: ${{ secrets.PRODUCTION_VPS_PORT }}
VPS_USER: ${{ secrets.PRODUCTION_VPS_USER }}
run: |
scp -P "$VPS_PORT" release-${GITHUB_SHA}.tgz
"$VPS_USER@$VPS_HOST:/tmp/release-${GITHUB_SHA}.tgz"

- name: Activate and verify release
env:
VPS_HOST: ${{ secrets.PRODUCTION_VPS_HOST }}
VPS_PORT: ${{ secrets.PRODUCTION_VPS_PORT }}
VPS_USER: ${{ secrets.PRODUCTION_VPS_USER }}
run: |
ssh -p "$VPS_PORT" "$VPS_USER@$VPS_HOST"
"RELEASE_SHA=$GITHUB_SHA bash -s" < .github/scripts/deploy-remote.sh

Pin third-party actions to reviewed commit SHAs or to maintained major versions. A mutable action reference can change what production executes without a change to your workflow file.

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Make the remote script idempotent

Place the activation logic in a version-controlled script such as .github/scripts/deploy-remote.sh. It should create a directory named for the commit SHA, unpack the artifact there, update the configuration or symlink, restart the service, and retain the previous release. Running it twice for the same SHA should converge on the same state rather than corrupting files.

#!/usr/bin/env bash
set -euo pipefail

: "${RELEASE_SHA:?missing release identifier}"
archive="/tmp/release-${RELEASE_SHA}.tgz"
release_dir="/srv/myapp/releases/${RELEASE_SHA}"
previous_target="$(readlink -f /srv/myapp/current 2>/dev/null || true)"

install -d -o deploy -g deploy "$release_dir"
tar -xzf "$archive" -C "$release_dir"
ln -sfn "$release_dir" /srv/myapp/current
sudo systemctl restart myapp.service

if ! curl --fail --silent --show-error --max-time 10 http://127.0.0.1:8080/health; then
if [ -n "$previous_target" ]; then
ln -sfn "$previous_target" /srv/myapp/current
sudo systemctl restart myapp.service
fi
exit 1
fi

rm -f "$archive"

Adapt paths, ports, and the service command to your application. The important properties are explicit versioning, a health gate, and an automatic return to the prior target if the new process does not become healthy. Keep several previous releases until your retention policy says they can be removed.

Rank #4
Sale
Vaydeer Wrist Rest for Keyboard and Mouse, Computer Ergonomic Wrist Support Pad, Soft Memory Foam Arm Cushion for Desk, Palm Hand Office Laptop Typing
  • 【Softer and More Comfortable】Vaydeer wrist rest has unique diamond pattern, which is the combination of softness and aesthetics. The materials of wrist rest are improved into higher quality memory foam and covered with silky smooth lycra. The computer wrist rest makes you as comfortable and cushiony as like rest your wrists on clouds.
  • 【Ergonomic Wrist Saver】The wrist rests for keyboard and mouse comes with a 17.32×3.15×0.83 inch keyboard wrist pad and a 5.94×3.15×0.83 inch mouse wrist support. Based on ergonomic design, the unique concave shape is the perfect fit for your wrist joints. The wrist rest pad fits most computer keyboards and laptops, improve hand and wrist posture, release your wrist and arm stress.
  • 【Non-Slip Rubber Bottom】Featuring an anti-skid silicone base on the bottom, this wrist keyboard support stays firmly in place on your desk, preventing the padding from sliding around, ensuring stable and consistent wrist support during extended computer sessions.
  • 【Better Experience & Pain Relief】Our keyboard arm rest is beneficial to alleviate the soreness caused by direct contact and friction between your arm and a hard desk surface, reducing the risk of wrist fatigue or carpal tunnel. The soft texture of memory foam can evenly distribute the pressure around your wrists and provide good support with just enough give.
  • 【Helpful in Multiple Scenarios】Whether you're working, studying, writing, typing, gaming, this keyboard and mouse rest combo is an essential accessory to add comfort and support to your hands and wrists. It’s also a great gift for men, women, family, friend, coworker, gamer, teacher, etc.

Record an audit trail

Write the commit SHA, workflow run, actor, and deployment timestamp to the release metadata or deployment log. This lets an operator answer which source revision is serving without inspecting a build workspace that no longer exists.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use a container image instead of an archive

For a containerized application, build the image once on the hosted runner and push it to a registry under an immutable commit-SHA tag. The VPS should pull that exact tag, update its compose or service configuration, and restart the service. Keep the previous image tag available so rollback does not depend on rebuilding source code.

Pass registry authentication through GitHub secrets and the VPS’s runtime secret store. Never print credentials in workflow logs. The same health-check and audit requirements apply whether the release is a tar archive or an image.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Deploy directly with a self-hosted runner

GitHub defines a self-hosted runner as “a system that you deploy and manage to execute jobs from GitHub Actions on GitHub.” The runner application must be running on the host to accept and run jobs. GitHub supports physical, virtual, containerized, on-premises, and cloud machines, but the operator remains responsible for the operating system and other software.

Best Value
Sale
Under Desk Cable Management Tray No Drill, Metal Mesh Cable Management Under Desk with Clamp Mount, 2 Hole Cable Tray with Wire Management and Cord Organizer for Home Office Standing Desk
  • 【No Drill Mounted】Cable management tray can be assembled in as little as 3 minutes or less-simply. Side clips easily clampe the edge of desk, pass through the holes on the sides, and secure excess cables with baskets. Desk cable management supports inward or outward installation to meet your needs in different scenarios, and provides you with great convenience when collecting and organizing wires.
  • 【Rubber Pad Protects Desk】Wire organizer under desk built-in soft rubber pads on the clamp protect your desk from scratches, so you will not damage your furniture or office.
  • 【Sturdy and Beautiful】Cord management under desk is made of high-quality carbon steel and holds about 15 lbs. The wire basket has 2 holes on each side of the tray to enable your cables to pass freely. Cable baskets are suitable for desk thickness use from 0.4" to 2.4".
  • 【Space Saving & Keep Organized】Desk cable management tray holds all your power cords, outlet strips, USB hubs and computer transformers hidden from your feet, and the data cables will not enter the vacuum cleaner to keep your desk clean and tidy. Desk wire organizer is also suitable for use in the kitchen and outdoors.
  • 【Reduce Safety Risks】Cable tray under desk keeps all plugs away from your kids, no more worry about tripping. Using 2 holes wire tray saves extra space, helps you easily cabling and wire protection. The mesh design is not easy to accumulate dust, but avoids safety accidents caused by messy wires.
  1. On the repository or organization, open Settings → Actions → Runners and choose New self-hosted runner.
  2. Select the VPS operating system and architecture. Copy the installation and registration commands generated by GitHub; the registration token shown there is temporary.
  3. Install the runner under a dedicated account, not as an unrestricted root process. Apply a distinctive label such as deploy-vps.
  4. Install the runtime, Docker, and service-manager dependencies that the workflow needs. Enable the runner as a service so it returns after a reboot, and monitor whether it remains online.
  5. Target the label in the workflow:
jobs:
deploy:
runs-on: [self-hosted, linux, deploy-vps]

A self-hosted runner gives the job direct access to local files, Docker sockets, and systemd. That convenience is also the main risk: a compromised workflow or dependency can reach the runner’s local trust boundary. Restrict which repositories may use the runner, avoid broad labels, patch the host and runner promptly, retain useful logs, and do not assume that a GitHub deployment environment creates a container boundary around the job.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Protect secrets and workflow permissions

  • Keep private keys and runtime credentials in GitHub secrets or environment secrets, never in YAML, source code, artifacts, or command-line arguments that may appear in logs.
  • Use a separate deployment account and key for each production trust boundary where practical.
  • Protect the production branch and require an environment approval before production secrets are exposed.
  • Use GITHUB_TOKEN for workflow-to-GitHub authentication only. GitHub’s runner authentication documentation states that this token expires after 60 minutes; it is not a substitute for separately scoped VPS credentials.
  • Mask sensitive values and avoid commands that echo complete environment blocks.
  • Pin third-party actions to reviewed commit SHAs or maintained major versions.
  • For self-hosted runners, limit repository access, inspect job logs, patch the operating system and runner, and assume that a job can access local credentials and sockets available to the runner account.

Health checks, rollback, and failure handling

Health-check the service, not just the process

A successful SSH command or a zero exit status from systemd does not prove that users can reach the application. Check an endpoint or command that exercises the dependencies needed for a real request. Fail the workflow when the check times out, returns an unexpected status, or reports an unhealthy dependency.

Keep a deterministic rollback

For archive deployments, retain the previous release directory and its configuration. For containers, retain the preceding image tag. Rollback should be a single documented command or script that selects the known-good version and restarts the service; it should not require a new build.

Handle partial failures

If transfer fails, leave the currently active release untouched. If extraction succeeds but activation fails, remove only the incomplete new directory. If activation succeeds but the health check fails, switch back to the previous target, restart, and report the failed SHA in the workflow. Make cleanup safe to repeat.

Troubleshoot the common failure modes

Symptom Likely cause What to check
Permission denied (publickey) The wrong private key, username, file mode, or public-key entry is being used. Confirm the secret contains the matching private key, the public key is in the deploy user’s authorized_keys, the key file is mode 600, and SSH is using the intended user and port.
Host-key verification failed The VPS host key is absent or changed. Review the change out of band, then update the protected known-hosts secret. Do not disable host-key checking to make the job pass.
Connection timeout Firewall rules, the wrong port, a stopped SSH service, or an unreachable address. Test the same hostname and port from an approved network, inspect VPS firewall rules, and confirm the workflow secret has no whitespace or stale address.
Runner is offline The self-hosted service stopped, the host rebooted, or capacity is exhausted. Check the runner service, disk and memory usage, labels, and the runner’s local diagnostic logs.
Service restarts but health check fails Bad configuration, missing runtime secret, incompatible migration, or a port mismatch. Inspect service logs, verify the rendered configuration, test the endpoint locally, and invoke the rollback path.
Deployment succeeds but serves old code The service still points at an old directory or image tag, or a cache is masking the change. Print the active symlink or running image ID, record the commit SHA at startup, and check reverse-proxy and application caches.
Rollback cannot start The previous artifact was deleted or depends on a changed shared configuration. Retain complete previous artifacts, version migrations carefully, and test rollback during a maintenance exercise.

A production-ready operating checklist

  • Build and test exactly once for the commit being deployed.
  • Publish a versioned archive or image identified by the commit SHA.
  • Use a dedicated non-root account and a dedicated deployment key.
  • Keep all private keys and runtime credentials in protected secrets or environments.
  • Verify the VPS host key instead of disabling SSH verification.
  • Require approval for production deployments and protect the source branch or tag.
  • Pin actions to reviewed SHAs or maintained major versions.
  • Make the remote script idempotent and retain the prior release.
  • Run a meaningful health check and fail the workflow on an unhealthy result.
  • Record the deployed SHA, actor, and timestamp.
  • Rotate keys, patch hosts, and remove runner access when ownership changes.

Which model should you use?

For most teams, start with a GitHub-hosted runner plus SSH. It keeps builds ephemeral, avoids running arbitrary pull-request code on the production host, and makes the VPS responsible mainly for serving the already-built release. Choose a self-hosted runner when local Docker or filesystem access is a real requirement and you can provide continuous patching, monitoring, capacity planning, restricted repository access, and a clear response plan for runner compromise.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.